diff --git a/.bin/wand b/.bin/wand new file mode 100755 index 0000000..6e21193 Binary files /dev/null and b/.bin/wand differ diff --git a/.cover b/.cover index e21ca3a..6819555 100644 --- a/.cover +++ b/.cover @@ -1,457 +1,1249 @@ mode: set -code.squareroundforest.org/arpio/wand/cmd/wand-docs/main.go:3.14,4.2 0 0 -code.squareroundforest.org/arpio/wand/apply.go:9.54,10.15 1 0 -code.squareroundforest.org/arpio/wand/apply.go:10.15,12.3 1 0 -code.squareroundforest.org/arpio/wand/apply.go:14.2,14.31 1 0 -code.squareroundforest.org/arpio/wand/apply.go:17.52,18.17 1 1 -code.squareroundforest.org/arpio/wand/apply.go:18.17,22.3 3 1 -code.squareroundforest.org/arpio/wand/apply.go:24.2,24.17 1 1 -code.squareroundforest.org/arpio/wand/apply.go:24.17,27.3 2 0 -code.squareroundforest.org/arpio/wand/apply.go:29.2,29.31 1 1 -code.squareroundforest.org/arpio/wand/apply.go:29.31,31.3 1 1 -code.squareroundforest.org/arpio/wand/apply.go:34.47,35.25 1 1 -code.squareroundforest.org/arpio/wand/apply.go:36.23,37.32 1 0 -code.squareroundforest.org/arpio/wand/apply.go:38.21,39.30 1 1 -code.squareroundforest.org/arpio/wand/apply.go:43.50,45.2 1 0 -code.squareroundforest.org/arpio/wand/apply.go:47.48,48.31 1 1 -code.squareroundforest.org/arpio/wand/apply.go:48.31,50.3 1 1 -code.squareroundforest.org/arpio/wand/apply.go:53.41,54.14 1 1 -code.squareroundforest.org/arpio/wand/apply.go:54.14,57.3 2 1 -code.squareroundforest.org/arpio/wand/apply.go:59.2,59.47 1 1 -code.squareroundforest.org/arpio/wand/apply.go:62.52,63.22 1 1 -code.squareroundforest.org/arpio/wand/apply.go:64.23,65.28 1 0 -code.squareroundforest.org/arpio/wand/apply.go:66.21,67.26 1 1 -code.squareroundforest.org/arpio/wand/apply.go:68.10,69.24 1 1 -code.squareroundforest.org/arpio/wand/apply.go:73.56,74.43 1 1 -code.squareroundforest.org/arpio/wand/apply.go:74.43,80.10 6 1 -code.squareroundforest.org/arpio/wand/apply.go:81.39,83.24 2 1 -code.squareroundforest.org/arpio/wand/apply.go:84.55,86.39 2 0 -code.squareroundforest.org/arpio/wand/apply.go:86.39,89.5 2 0 -code.squareroundforest.org/arpio/wand/apply.go:90.21,92.33 2 0 -code.squareroundforest.org/arpio/wand/apply.go:97.100,101.23 4 1 -code.squareroundforest.org/arpio/wand/apply.go:101.23,103.3 1 1 -code.squareroundforest.org/arpio/wand/apply.go:105.2,106.42 2 1 -code.squareroundforest.org/arpio/wand/apply.go:106.42,109.3 2 1 -code.squareroundforest.org/arpio/wand/apply.go:111.2,112.23 2 1 -code.squareroundforest.org/arpio/wand/apply.go:112.23,114.41 2 1 -code.squareroundforest.org/arpio/wand/apply.go:114.41,116.4 1 1 -code.squareroundforest.org/arpio/wand/apply.go:118.3,118.28 1 1 -code.squareroundforest.org/arpio/wand/apply.go:121.2,122.26 2 1 -code.squareroundforest.org/arpio/wand/apply.go:122.26,123.12 1 1 -code.squareroundforest.org/arpio/wand/apply.go:123.12,125.4 1 1 -code.squareroundforest.org/arpio/wand/apply.go:128.2,129.20 2 1 -code.squareroundforest.org/arpio/wand/apply.go:129.20,130.12 1 1 -code.squareroundforest.org/arpio/wand/apply.go:130.12,132.4 1 1 -code.squareroundforest.org/arpio/wand/apply.go:135.2,135.50 1 1 -code.squareroundforest.org/arpio/wand/apply.go:135.50,137.3 1 1 -code.squareroundforest.org/arpio/wand/apply.go:139.2,140.29 2 1 -code.squareroundforest.org/arpio/wand/apply.go:140.29,142.34 2 1 -code.squareroundforest.org/arpio/wand/apply.go:142.34,144.4 1 1 -code.squareroundforest.org/arpio/wand/apply.go:146.3,146.27 1 1 -code.squareroundforest.org/arpio/wand/apply.go:149.2,149.33 1 1 -code.squareroundforest.org/arpio/wand/apply.go:149.33,151.28 2 1 -code.squareroundforest.org/arpio/wand/apply.go:151.28,153.4 1 1 -code.squareroundforest.org/arpio/wand/apply.go:155.3,155.27 1 1 -code.squareroundforest.org/arpio/wand/apply.go:158.2,158.32 1 1 -code.squareroundforest.org/arpio/wand/apply.go:161.63,165.2 3 1 -code.squareroundforest.org/arpio/wand/apply.go:167.93,170.33 3 1 -code.squareroundforest.org/arpio/wand/apply.go:170.33,174.28 4 1 -code.squareroundforest.org/arpio/wand/apply.go:174.28,175.69 1 0 -code.squareroundforest.org/arpio/wand/apply.go:175.69,177.5 1 0 -code.squareroundforest.org/arpio/wand/apply.go:178.9,178.23 1 1 -code.squareroundforest.org/arpio/wand/apply.go:178.23,181.4 2 1 -code.squareroundforest.org/arpio/wand/apply.go:181.9,181.22 1 1 -code.squareroundforest.org/arpio/wand/apply.go:181.22,182.33 1 1 -code.squareroundforest.org/arpio/wand/apply.go:182.33,184.5 1 1 -code.squareroundforest.org/arpio/wand/apply.go:185.9,189.4 3 1 -code.squareroundforest.org/arpio/wand/apply.go:192.2,192.13 1 1 -code.squareroundforest.org/arpio/wand/apply.go:195.73,196.19 1 1 -code.squareroundforest.org/arpio/wand/apply.go:196.19,198.3 1 0 -code.squareroundforest.org/arpio/wand/apply.go:200.2,203.40 4 1 -code.squareroundforest.org/arpio/wand/apply.go:203.40,205.3 1 0 -code.squareroundforest.org/arpio/wand/apply.go:207.2,207.17 1 1 -code.squareroundforest.org/arpio/wand/apply.go:207.17,209.3 1 0 -code.squareroundforest.org/arpio/wand/apply.go:211.2,212.24 2 1 -code.squareroundforest.org/arpio/wand/apply.go:212.24,214.3 1 1 -code.squareroundforest.org/arpio/wand/apply.go:216.2,216.20 1 1 -code.squareroundforest.org/arpio/wand/apply.go:219.59,226.2 6 1 -code.squareroundforest.org/arpio/wand/command.go:9.57,15.2 1 1 -code.squareroundforest.org/arpio/wand/command.go:17.25,19.8 2 1 -code.squareroundforest.org/arpio/wand/command.go:19.8,21.3 1 1 -code.squareroundforest.org/arpio/wand/command.go:23.2,23.26 1 1 -code.squareroundforest.org/arpio/wand/command.go:26.38,28.23 2 1 -code.squareroundforest.org/arpio/wand/command.go:28.23,29.68 1 1 -code.squareroundforest.org/arpio/wand/command.go:29.68,31.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:33.3,33.19 1 1 -code.squareroundforest.org/arpio/wand/command.go:36.2,36.12 1 1 -code.squareroundforest.org/arpio/wand/command.go:39.46,40.18 1 1 -code.squareroundforest.org/arpio/wand/command.go:54.18,55.13 1 1 -code.squareroundforest.org/arpio/wand/command.go:57.17,59.30 2 0 -code.squareroundforest.org/arpio/wand/command.go:60.25,61.24 1 0 -code.squareroundforest.org/arpio/wand/command.go:61.24,63.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:65.3,65.13 1 0 -code.squareroundforest.org/arpio/wand/command.go:66.10,67.57 1 0 -code.squareroundforest.org/arpio/wand/command.go:71.61,73.23 2 1 -code.squareroundforest.org/arpio/wand/command.go:73.23,74.47 1 1 -code.squareroundforest.org/arpio/wand/command.go:74.47,76.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:79.2,81.18 3 1 -code.squareroundforest.org/arpio/wand/command.go:81.18,83.3 1 1 -code.squareroundforest.org/arpio/wand/command.go:85.2,85.38 1 1 -code.squareroundforest.org/arpio/wand/command.go:85.38,91.3 1 0 -code.squareroundforest.org/arpio/wand/command.go:93.2,93.55 1 1 -code.squareroundforest.org/arpio/wand/command.go:93.55,99.3 1 0 -code.squareroundforest.org/arpio/wand/command.go:101.2,101.38 1 1 -code.squareroundforest.org/arpio/wand/command.go:101.38,107.3 1 0 -code.squareroundforest.org/arpio/wand/command.go:109.2,109.37 1 1 -code.squareroundforest.org/arpio/wand/command.go:109.37,115.3 1 0 -code.squareroundforest.org/arpio/wand/command.go:117.2,117.12 1 1 -code.squareroundforest.org/arpio/wand/command.go:120.34,124.30 4 1 -code.squareroundforest.org/arpio/wand/command.go:124.30,126.3 1 0 -code.squareroundforest.org/arpio/wand/command.go:128.2,130.42 3 1 -code.squareroundforest.org/arpio/wand/command.go:130.42,132.3 1 0 -code.squareroundforest.org/arpio/wand/command.go:134.2,134.84 1 1 -code.squareroundforest.org/arpio/wand/command.go:134.84,136.3 1 0 -code.squareroundforest.org/arpio/wand/command.go:138.2,138.12 1 1 -code.squareroundforest.org/arpio/wand/command.go:141.40,144.32 3 1 -code.squareroundforest.org/arpio/wand/command.go:144.32,148.3 1 0 -code.squareroundforest.org/arpio/wand/command.go:150.2,150.46 1 1 -code.squareroundforest.org/arpio/wand/command.go:150.46,153.27 3 1 -code.squareroundforest.org/arpio/wand/command.go:153.27,155.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:157.3,157.51 1 1 -code.squareroundforest.org/arpio/wand/command.go:157.51,159.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:161.3,161.26 1 1 -code.squareroundforest.org/arpio/wand/command.go:161.26,163.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:165.3,165.39 1 1 -code.squareroundforest.org/arpio/wand/command.go:165.39,167.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:169.3,169.14 1 1 -code.squareroundforest.org/arpio/wand/command.go:172.2,172.12 1 1 -code.squareroundforest.org/arpio/wand/command.go:175.37,176.19 1 1 -code.squareroundforest.org/arpio/wand/command.go:176.19,178.6 1 1 -code.squareroundforest.org/arpio/wand/command.go:180.2,180.21 1 1 -code.squareroundforest.org/arpio/wand/command.go:180.21,181.43 1 1 -code.squareroundforest.org/arpio/wand/command.go:181.43,183.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:186.2,186.50 1 1 -code.squareroundforest.org/arpio/wand/command.go:186.50,188.3 1 0 -code.squareroundforest.org/arpio/wand/command.go:190.5,190.24 1 1 -code.squareroundforest.org/arpio/wand/command.go:190.24,191.55 1 1 -code.squareroundforest.org/arpio/wand/command.go:191.55,193.10 1 0 -code.squareroundforest.org/arpio/wand/command.go:196.5,198.36 3 1 -code.squareroundforest.org/arpio/wand/command.go:198.36,199.19 1 1 -code.squareroundforest.org/arpio/wand/command.go:199.19,201.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:203.3,203.20 1 1 -code.squareroundforest.org/arpio/wand/command.go:203.20,205.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:207.3,208.44 2 1 -code.squareroundforest.org/arpio/wand/command.go:208.44,210.4 1 0 -code.squareroundforest.org/arpio/wand/command.go:212.9,212.38 1 1 -code.squareroundforest.org/arpio/wand/command.go:212.38,214.10 1 0 -code.squareroundforest.org/arpio/wand/command.go:216.9,216.24 1 1 -code.squareroundforest.org/arpio/wand/command.go:216.24,218.10 1 1 -code.squareroundforest.org/arpio/wand/command.go:221.2,221.12 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:28.30,30.2 1 1 +code.squareroundforest.org/arpio/wand/apply.go:10.54,11.15 1 0 +code.squareroundforest.org/arpio/wand/apply.go:11.15,13.3 1 0 +code.squareroundforest.org/arpio/wand/apply.go:15.2,15.31 1 0 +code.squareroundforest.org/arpio/wand/apply.go:18.52,19.17 1 0 +code.squareroundforest.org/arpio/wand/apply.go:19.17,23.3 3 0 +code.squareroundforest.org/arpio/wand/apply.go:25.2,25.17 1 0 +code.squareroundforest.org/arpio/wand/apply.go:25.17,28.3 2 0 +code.squareroundforest.org/arpio/wand/apply.go:30.2,30.31 1 0 +code.squareroundforest.org/arpio/wand/apply.go:30.31,32.3 1 0 +code.squareroundforest.org/arpio/wand/apply.go:35.47,36.25 1 1 +code.squareroundforest.org/arpio/wand/apply.go:37.23,38.32 1 0 +code.squareroundforest.org/arpio/wand/apply.go:39.21,40.30 1 0 +code.squareroundforest.org/arpio/wand/apply.go:44.50,46.2 1 0 +code.squareroundforest.org/arpio/wand/apply.go:48.48,49.31 1 0 +code.squareroundforest.org/arpio/wand/apply.go:49.31,51.3 1 0 +code.squareroundforest.org/arpio/wand/apply.go:54.41,55.14 1 1 +code.squareroundforest.org/arpio/wand/apply.go:55.14,58.3 2 0 +code.squareroundforest.org/arpio/wand/apply.go:60.2,60.47 1 1 +code.squareroundforest.org/arpio/wand/apply.go:63.52,64.22 1 1 +code.squareroundforest.org/arpio/wand/apply.go:65.23,66.28 1 0 +code.squareroundforest.org/arpio/wand/apply.go:67.21,68.26 1 0 +code.squareroundforest.org/arpio/wand/apply.go:69.10,70.24 1 1 +code.squareroundforest.org/arpio/wand/apply.go:74.56,75.43 1 1 +code.squareroundforest.org/arpio/wand/apply.go:75.43,81.10 6 1 +code.squareroundforest.org/arpio/wand/apply.go:82.39,84.24 2 1 +code.squareroundforest.org/arpio/wand/apply.go:85.55,87.39 2 0 +code.squareroundforest.org/arpio/wand/apply.go:87.39,90.5 2 0 +code.squareroundforest.org/arpio/wand/apply.go:91.21,93.33 2 0 +code.squareroundforest.org/arpio/wand/apply.go:98.110,102.23 4 1 +code.squareroundforest.org/arpio/wand/apply.go:102.23,104.3 1 1 +code.squareroundforest.org/arpio/wand/apply.go:106.2,107.42 2 1 +code.squareroundforest.org/arpio/wand/apply.go:107.42,110.3 2 0 +code.squareroundforest.org/arpio/wand/apply.go:112.2,113.23 2 1 +code.squareroundforest.org/arpio/wand/apply.go:113.23,115.41 2 1 +code.squareroundforest.org/arpio/wand/apply.go:115.41,117.4 1 0 +code.squareroundforest.org/arpio/wand/apply.go:119.3,119.28 1 1 +code.squareroundforest.org/arpio/wand/apply.go:122.2,123.26 2 1 +code.squareroundforest.org/arpio/wand/apply.go:123.26,124.12 1 0 +code.squareroundforest.org/arpio/wand/apply.go:124.12,126.4 1 0 +code.squareroundforest.org/arpio/wand/apply.go:129.2,130.26 2 1 +code.squareroundforest.org/arpio/wand/apply.go:130.26,131.12 1 0 +code.squareroundforest.org/arpio/wand/apply.go:131.12,133.4 1 0 +code.squareroundforest.org/arpio/wand/apply.go:136.2,137.20 2 1 +code.squareroundforest.org/arpio/wand/apply.go:137.20,138.12 1 1 +code.squareroundforest.org/arpio/wand/apply.go:138.12,140.4 1 1 +code.squareroundforest.org/arpio/wand/apply.go:143.2,143.75 1 1 +code.squareroundforest.org/arpio/wand/apply.go:143.75,145.3 1 0 +code.squareroundforest.org/arpio/wand/apply.go:147.2,148.32 2 1 +code.squareroundforest.org/arpio/wand/apply.go:148.32,150.34 2 0 +code.squareroundforest.org/arpio/wand/apply.go:150.34,152.4 1 0 +code.squareroundforest.org/arpio/wand/apply.go:154.3,154.27 1 0 +code.squareroundforest.org/arpio/wand/apply.go:157.2,157.29 1 1 +code.squareroundforest.org/arpio/wand/apply.go:157.29,159.34 2 0 +code.squareroundforest.org/arpio/wand/apply.go:159.34,161.4 1 0 +code.squareroundforest.org/arpio/wand/apply.go:163.3,163.27 1 0 +code.squareroundforest.org/arpio/wand/apply.go:166.2,166.33 1 1 +code.squareroundforest.org/arpio/wand/apply.go:166.33,168.28 2 1 +code.squareroundforest.org/arpio/wand/apply.go:168.28,170.4 1 1 +code.squareroundforest.org/arpio/wand/apply.go:172.3,172.27 1 1 +code.squareroundforest.org/arpio/wand/apply.go:175.2,175.32 1 1 +code.squareroundforest.org/arpio/wand/apply.go:178.63,179.35 1 1 +code.squareroundforest.org/arpio/wand/apply.go:179.35,181.3 1 1 +code.squareroundforest.org/arpio/wand/apply.go:183.2,185.20 3 1 +code.squareroundforest.org/arpio/wand/apply.go:188.138,191.33 3 1 +code.squareroundforest.org/arpio/wand/apply.go:191.33,197.10 6 1 +code.squareroundforest.org/arpio/wand/apply.go:198.12,199.47 1 1 +code.squareroundforest.org/arpio/wand/apply.go:200.12,201.48 1 1 +code.squareroundforest.org/arpio/wand/apply.go:202.30,203.72 1 0 +code.squareroundforest.org/arpio/wand/apply.go:203.72,205.5 1 0 +code.squareroundforest.org/arpio/wand/apply.go:206.18,208.28 2 1 +code.squareroundforest.org/arpio/wand/apply.go:209.17,210.33 1 0 +code.squareroundforest.org/arpio/wand/apply.go:210.33,212.5 1 0 +code.squareroundforest.org/arpio/wand/apply.go:213.11,216.48 3 1 +code.squareroundforest.org/arpio/wand/apply.go:220.2,220.13 1 1 +code.squareroundforest.org/arpio/wand/apply.go:223.73,224.19 1 1 +code.squareroundforest.org/arpio/wand/apply.go:224.19,226.3 1 1 +code.squareroundforest.org/arpio/wand/apply.go:228.2,231.40 4 1 +code.squareroundforest.org/arpio/wand/apply.go:231.40,233.3 1 0 +code.squareroundforest.org/arpio/wand/apply.go:235.2,235.17 1 1 +code.squareroundforest.org/arpio/wand/apply.go:235.17,237.3 1 0 +code.squareroundforest.org/arpio/wand/apply.go:239.2,240.24 2 1 +code.squareroundforest.org/arpio/wand/apply.go:240.24,242.3 1 1 +code.squareroundforest.org/arpio/wand/apply.go:244.2,244.20 1 1 +code.squareroundforest.org/arpio/wand/apply.go:247.104,254.2 6 1 +code.squareroundforest.org/arpio/wand/command.go:13.57,19.2 1 1 +code.squareroundforest.org/arpio/wand/command.go:21.25,23.8 2 1 +code.squareroundforest.org/arpio/wand/command.go:23.8,25.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:27.2,27.26 1 1 +code.squareroundforest.org/arpio/wand/command.go:30.51,33.23 3 1 +code.squareroundforest.org/arpio/wand/command.go:33.23,34.68 1 1 +code.squareroundforest.org/arpio/wand/command.go:34.68,36.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:38.3,38.49 1 1 +code.squareroundforest.org/arpio/wand/command.go:38.49,40.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:42.3,42.19 1 1 +code.squareroundforest.org/arpio/wand/command.go:45.2,45.12 1 1 +code.squareroundforest.org/arpio/wand/command.go:48.77,49.18 1 1 +code.squareroundforest.org/arpio/wand/command.go:63.18,64.13 1 1 +code.squareroundforest.org/arpio/wand/command.go:66.17,67.17 1 0 +code.squareroundforest.org/arpio/wand/command.go:67.17,69.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:71.3,71.21 1 0 +code.squareroundforest.org/arpio/wand/command.go:71.21,73.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:75.3,77.39 3 0 +code.squareroundforest.org/arpio/wand/command.go:78.25,79.24 1 1 +code.squareroundforest.org/arpio/wand/command.go:79.24,81.4 1 1 +code.squareroundforest.org/arpio/wand/command.go:83.3,83.13 1 1 +code.squareroundforest.org/arpio/wand/command.go:84.10,85.57 1 1 +code.squareroundforest.org/arpio/wand/command.go:89.61,92.34 3 1 +code.squareroundforest.org/arpio/wand/command.go:92.34,94.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:96.2,96.23 1 1 +code.squareroundforest.org/arpio/wand/command.go:96.23,97.57 1 1 +code.squareroundforest.org/arpio/wand/command.go:97.57,98.12 1 1 +code.squareroundforest.org/arpio/wand/command.go:101.3,101.52 1 1 +code.squareroundforest.org/arpio/wand/command.go:101.52,103.4 1 1 +code.squareroundforest.org/arpio/wand/command.go:106.2,112.18 4 1 +code.squareroundforest.org/arpio/wand/command.go:112.18,114.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:116.2,116.38 1 1 +code.squareroundforest.org/arpio/wand/command.go:116.38,122.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:124.2,124.55 1 1 +code.squareroundforest.org/arpio/wand/command.go:124.55,130.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:132.2,132.38 1 1 +code.squareroundforest.org/arpio/wand/command.go:132.38,138.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:140.2,140.37 1 1 +code.squareroundforest.org/arpio/wand/command.go:140.37,146.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:148.2,148.12 1 1 +code.squareroundforest.org/arpio/wand/command.go:151.47,155.30 4 1 +code.squareroundforest.org/arpio/wand/command.go:155.30,157.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:159.2,161.16 3 1 +code.squareroundforest.org/arpio/wand/command.go:161.16,163.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:165.2,165.48 1 1 +code.squareroundforest.org/arpio/wand/command.go:165.48,167.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:169.2,169.84 1 1 +code.squareroundforest.org/arpio/wand/command.go:169.84,171.3 1 1 +code.squareroundforest.org/arpio/wand/command.go:173.2,173.12 1 1 +code.squareroundforest.org/arpio/wand/command.go:176.78,178.32 2 1 +code.squareroundforest.org/arpio/wand/command.go:178.32,182.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:184.2,184.46 1 1 +code.squareroundforest.org/arpio/wand/command.go:184.46,187.51 3 0 +code.squareroundforest.org/arpio/wand/command.go:187.51,189.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:191.3,191.26 1 0 +code.squareroundforest.org/arpio/wand/command.go:191.26,193.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:195.3,195.27 1 0 +code.squareroundforest.org/arpio/wand/command.go:195.27,196.12 1 0 +code.squareroundforest.org/arpio/wand/command.go:199.3,199.55 1 0 +code.squareroundforest.org/arpio/wand/command.go:199.55,201.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:203.3,203.30 1 0 +code.squareroundforest.org/arpio/wand/command.go:206.2,206.12 1 1 +code.squareroundforest.org/arpio/wand/command.go:209.103,210.16 1 1 +code.squareroundforest.org/arpio/wand/command.go:210.16,212.3 1 1 +code.squareroundforest.org/arpio/wand/command.go:214.2,214.23 1 1 +code.squareroundforest.org/arpio/wand/command.go:214.23,216.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:218.2,218.59 1 1 +code.squareroundforest.org/arpio/wand/command.go:218.59,220.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:222.2,222.21 1 1 +code.squareroundforest.org/arpio/wand/command.go:222.21,223.49 1 1 +code.squareroundforest.org/arpio/wand/command.go:223.49,225.4 1 1 +code.squareroundforest.org/arpio/wand/command.go:228.2,228.50 1 1 +code.squareroundforest.org/arpio/wand/command.go:228.50,230.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:232.2,232.21 1 1 +code.squareroundforest.org/arpio/wand/command.go:232.21,233.69 1 1 +code.squareroundforest.org/arpio/wand/command.go:233.69,235.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:238.2,240.36 3 1 +code.squareroundforest.org/arpio/wand/command.go:240.36,241.19 1 1 +code.squareroundforest.org/arpio/wand/command.go:241.19,243.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:245.3,245.20 1 1 +code.squareroundforest.org/arpio/wand/command.go:245.20,247.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:249.3,250.81 2 1 +code.squareroundforest.org/arpio/wand/command.go:250.81,252.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:254.3,254.37 1 1 +code.squareroundforest.org/arpio/wand/command.go:254.37,260.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:262.3,262.32 1 1 +code.squareroundforest.org/arpio/wand/command.go:262.32,264.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:266.3,266.18 1 1 +code.squareroundforest.org/arpio/wand/command.go:266.18,268.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:271.2,271.12 1 1 +code.squareroundforest.org/arpio/wand/command.go:274.38,276.37 2 1 +code.squareroundforest.org/arpio/wand/command.go:276.37,278.3 1 1 +code.squareroundforest.org/arpio/wand/command.go:280.2,280.46 1 1 +code.squareroundforest.org/arpio/wand/command.go:280.46,282.3 1 0 +code.squareroundforest.org/arpio/wand/command.go:284.2,284.11 1 1 +code.squareroundforest.org/arpio/wand/command.go:287.50,289.81 2 1 +code.squareroundforest.org/arpio/wand/command.go:289.81,291.3 1 1 +code.squareroundforest.org/arpio/wand/command.go:293.2,294.25 2 1 +code.squareroundforest.org/arpio/wand/command.go:294.25,295.43 1 0 +code.squareroundforest.org/arpio/wand/command.go:295.43,297.4 1 0 +code.squareroundforest.org/arpio/wand/command.go:300.2,300.12 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:28.30,30.2 1 0 code.squareroundforest.org/arpio/wand/commandline.go:32.34,34.2 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:36.48,37.29 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:37.29,38.24 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:38.24,40.10 1 0 -code.squareroundforest.org/arpio/wand/commandline.go:43.5,43.33 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:46.56,47.35 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:47.35,48.22 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:48.22,50.10 1 0 -code.squareroundforest.org/arpio/wand/commandline.go:53.5,53.35 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:36.48,37.26 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:37.26,38.18 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:38.18,40.4 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:43.2,43.30 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:46.56,47.32 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:47.32,48.16 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:48.16,50.4 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:53.2,53.32 1 1 code.squareroundforest.org/arpio/wand/commandline.go:56.36,65.23 8 1 -code.squareroundforest.org/arpio/wand/commandline.go:65.23,67.3 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:69.5,71.46 3 1 -code.squareroundforest.org/arpio/wand/commandline.go:71.46,74.3 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:65.23,67.3 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:69.2,71.46 3 1 +code.squareroundforest.org/arpio/wand/commandline.go:71.46,74.3 2 0 code.squareroundforest.org/arpio/wand/commandline.go:76.2,77.23 2 1 code.squareroundforest.org/arpio/wand/commandline.go:77.23,78.28 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:78.28,80.4 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:83.5,84.25 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:78.28,80.4 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:83.2,84.25 2 1 code.squareroundforest.org/arpio/wand/commandline.go:87.32,89.17 2 1 code.squareroundforest.org/arpio/wand/commandline.go:89.17,91.3 1 1 code.squareroundforest.org/arpio/wand/commandline.go:93.2,93.27 1 1 code.squareroundforest.org/arpio/wand/commandline.go:93.27,95.3 1 1 code.squareroundforest.org/arpio/wand/commandline.go:97.2,97.28 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:97.28,99.3 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:97.28,99.3 1 0 code.squareroundforest.org/arpio/wand/commandline.go:101.2,101.26 1 1 code.squareroundforest.org/arpio/wand/commandline.go:101.26,102.25 1 1 code.squareroundforest.org/arpio/wand/commandline.go:102.25,103.12 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:106.3,106.25 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:106.25,107.12 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:110.3,110.15 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:110.15,111.12 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:114.3,114.15 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:114.15,116.4 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:118.3,118.15 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:106.3,106.25 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:106.25,107.12 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:110.3,110.15 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:110.15,111.12 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:114.3,114.15 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:114.15,116.4 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:118.3,118.15 1 0 code.squareroundforest.org/arpio/wand/commandline.go:121.2,121.13 1 1 code.squareroundforest.org/arpio/wand/commandline.go:124.40,126.16 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:126.16,128.3 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:126.16,128.3 1 0 code.squareroundforest.org/arpio/wand/commandline.go:130.2,130.17 1 1 code.squareroundforest.org/arpio/wand/commandline.go:130.17,132.3 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:134.2,134.28 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:134.28,136.3 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:138.2,138.26 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:138.26,139.15 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:139.15,141.4 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:143.3,143.26 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:143.26,145.4 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:148.2,148.13 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:151.34,152.24 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:152.24,154.6 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:156.5,156.40 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:156.40,157.25 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:157.25,159.10 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:162.5,162.15 1 0 -code.squareroundforest.org/arpio/wand/commandline.go:165.51,166.40 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:166.40,167.28 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:167.28,169.10 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:172.5,172.24 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:175.70,176.23 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:176.23,178.6 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:180.5,181.12 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:181.12,183.6 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:185.5,185.18 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:185.18,188.6 2 0 -code.squareroundforest.org/arpio/wand/commandline.go:190.5,192.34 3 1 -code.squareroundforest.org/arpio/wand/commandline.go:195.49,200.2 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:202.46,207.2 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:209.33,212.2 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:214.34,215.17 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:215.17,217.3 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:219.2,219.19 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:219.19,221.3 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:223.2,223.27 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:223.27,225.3 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:227.2,227.13 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:230.38,233.2 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:235.85,237.14 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:237.14,239.65 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:239.65,242.4 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:244.3,244.40 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:247.2,252.19 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:252.19,256.3 3 1 -code.squareroundforest.org/arpio/wand/commandline.go:258.2,258.39 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:258.39,260.25 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:260.25,263.4 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:265.3,265.38 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:268.2,268.21 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:268.21,270.3 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:272.2,272.42 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:275.95,278.14 3 1 -code.squareroundforest.org/arpio/wand/commandline.go:278.14,280.3 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:282.2,283.31 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:283.31,285.3 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:287.2,287.94 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:287.94,290.3 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:292.2,295.16 4 1 -code.squareroundforest.org/arpio/wand/commandline.go:298.55,300.20 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:300.20,302.3 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:304.2,305.9 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:306.19,307.20 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:307.20,311.4 3 1 -code.squareroundforest.org/arpio/wand/commandline.go:312.21,316.35 4 1 -code.squareroundforest.org/arpio/wand/commandline.go:317.29,321.38 4 1 -code.squareroundforest.org/arpio/wand/commandline.go:322.10,323.43 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:326.2,329.10 4 1 -code.squareroundforest.org/arpio/wand/commandline.go:332.46,334.24 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:334.24,336.6 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:338.5,339.49 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:339.49,342.6 2 1 -code.squareroundforest.org/arpio/wand/commandline.go:344.5,344.26 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:344.26,345.29 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:345.29,346.21 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:349.9,349.30 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:349.30,350.41 1 0 -code.squareroundforest.org/arpio/wand/commandline.go:350.41,352.14 1 0 -code.squareroundforest.org/arpio/wand/commandline.go:355.9,355.43 1 1 -code.squareroundforest.org/arpio/wand/commandline.go:355.43,356.25 1 0 -code.squareroundforest.org/arpio/wand/commandline.go:356.25,358.14 1 0 -code.squareroundforest.org/arpio/wand/commandline.go:362.5,362.17 1 1 -code.squareroundforest.org/arpio/wand/env.go:13.39,20.30 2 1 -code.squareroundforest.org/arpio/wand/env.go:20.30,21.13 1 1 -code.squareroundforest.org/arpio/wand/env.go:21.13,24.12 3 1 -code.squareroundforest.org/arpio/wand/env.go:27.3,27.16 1 1 -code.squareroundforest.org/arpio/wand/env.go:27.16,29.12 2 1 -code.squareroundforest.org/arpio/wand/env.go:32.3,32.15 1 1 -code.squareroundforest.org/arpio/wand/env.go:32.15,35.12 3 1 -code.squareroundforest.org/arpio/wand/env.go:38.3,38.31 1 1 -code.squareroundforest.org/arpio/wand/env.go:41.2,42.15 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:134.2,134.28 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:134.28,136.3 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:138.2,138.26 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:138.26,139.15 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:139.15,141.4 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:143.3,143.26 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:143.26,145.4 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:148.2,148.13 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:151.34,152.21 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:152.21,154.3 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:156.2,156.37 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:156.37,157.19 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:157.19,159.4 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:162.2,162.12 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:165.51,166.37 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:166.37,167.22 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:167.22,169.4 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:172.2,172.21 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:175.70,176.20 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:176.20,178.3 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:180.2,181.9 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:181.9,183.3 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:185.2,187.31 3 0 +code.squareroundforest.org/arpio/wand/commandline.go:190.49,195.2 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:197.46,202.2 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:204.33,207.2 2 0 +code.squareroundforest.org/arpio/wand/commandline.go:209.34,210.17 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:210.17,212.3 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:214.2,214.19 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:214.19,216.3 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:218.2,218.27 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:218.27,220.3 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:222.2,222.13 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:225.38,228.2 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:230.85,232.14 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:232.14,234.65 2 0 +code.squareroundforest.org/arpio/wand/commandline.go:234.65,237.4 2 0 +code.squareroundforest.org/arpio/wand/commandline.go:239.3,239.40 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:242.2,247.19 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:247.19,251.3 3 1 +code.squareroundforest.org/arpio/wand/commandline.go:253.2,253.39 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:253.39,255.25 2 0 +code.squareroundforest.org/arpio/wand/commandline.go:255.25,258.4 2 0 +code.squareroundforest.org/arpio/wand/commandline.go:260.3,260.38 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:263.2,263.21 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:263.21,265.3 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:267.2,267.42 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:270.95,273.14 3 0 +code.squareroundforest.org/arpio/wand/commandline.go:273.14,275.3 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:277.2,278.31 2 0 +code.squareroundforest.org/arpio/wand/commandline.go:278.31,280.3 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:282.2,282.94 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:282.94,285.3 2 0 +code.squareroundforest.org/arpio/wand/commandline.go:287.2,290.16 4 0 +code.squareroundforest.org/arpio/wand/commandline.go:293.55,295.20 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:295.20,297.3 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:299.2,300.9 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:301.19,302.20 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:302.20,306.4 3 0 +code.squareroundforest.org/arpio/wand/commandline.go:307.21,311.35 4 1 +code.squareroundforest.org/arpio/wand/commandline.go:312.29,316.38 4 0 +code.squareroundforest.org/arpio/wand/commandline.go:317.10,318.43 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:321.2,324.10 4 1 +code.squareroundforest.org/arpio/wand/commandline.go:327.46,329.21 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:329.21,331.3 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:333.2,334.46 2 1 +code.squareroundforest.org/arpio/wand/commandline.go:334.46,337.3 2 0 +code.squareroundforest.org/arpio/wand/commandline.go:339.2,339.23 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:339.23,340.23 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:340.23,341.12 1 1 +code.squareroundforest.org/arpio/wand/commandline.go:344.3,344.24 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:344.24,345.32 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:345.32,347.5 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:350.3,350.37 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:350.37,351.16 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:351.16,353.5 1 0 +code.squareroundforest.org/arpio/wand/commandline.go:357.2,357.14 1 1 +code.squareroundforest.org/arpio/wand/config.go:24.40,28.2 1 0 +code.squareroundforest.org/arpio/wand/config.go:30.41,32.2 1 0 +code.squareroundforest.org/arpio/wand/config.go:34.44,35.19 1 0 +code.squareroundforest.org/arpio/wand/config.go:35.19,37.17 2 0 +code.squareroundforest.org/arpio/wand/config.go:37.17,39.4 1 0 +code.squareroundforest.org/arpio/wand/config.go:41.3,41.16 1 0 +code.squareroundforest.org/arpio/wand/config.go:44.2,45.16 2 0 +code.squareroundforest.org/arpio/wand/config.go:45.16,47.3 1 0 +code.squareroundforest.org/arpio/wand/config.go:49.2,49.15 1 0 +code.squareroundforest.org/arpio/wand/config.go:52.30,53.19 1 0 +code.squareroundforest.org/arpio/wand/config.go:53.19,55.3 1 0 +code.squareroundforest.org/arpio/wand/config.go:57.2,57.39 1 0 +code.squareroundforest.org/arpio/wand/config.go:57.39,59.3 1 0 +code.squareroundforest.org/arpio/wand/config.go:61.2,61.12 1 0 +code.squareroundforest.org/arpio/wand/config.go:64.59,66.21 2 0 +code.squareroundforest.org/arpio/wand/config.go:66.21,69.3 2 0 +code.squareroundforest.org/arpio/wand/config.go:69.8,71.3 1 0 +code.squareroundforest.org/arpio/wand/config.go:73.2,74.16 2 0 +code.squareroundforest.org/arpio/wand/config.go:74.16,75.92 1 0 +code.squareroundforest.org/arpio/wand/config.go:75.92,77.4 1 0 +code.squareroundforest.org/arpio/wand/config.go:79.3,79.69 1 0 +code.squareroundforest.org/arpio/wand/config.go:82.2,83.34 2 0 +code.squareroundforest.org/arpio/wand/config.go:83.34,84.30 1 0 +code.squareroundforest.org/arpio/wand/config.go:84.30,85.12 1 0 +code.squareroundforest.org/arpio/wand/config.go:88.3,94.37 2 0 +code.squareroundforest.org/arpio/wand/config.go:94.37,95.27 1 0 +code.squareroundforest.org/arpio/wand/config.go:95.27,97.13 2 0 +code.squareroundforest.org/arpio/wand/config.go:100.4,100.29 1 0 +code.squareroundforest.org/arpio/wand/config.go:100.29,103.13 3 0 +code.squareroundforest.org/arpio/wand/config.go:107.3,107.29 1 0 +code.squareroundforest.org/arpio/wand/config.go:107.29,109.4 1 0 +code.squareroundforest.org/arpio/wand/config.go:111.3,113.16 3 0 +code.squareroundforest.org/arpio/wand/config.go:113.16,115.12 2 0 +code.squareroundforest.org/arpio/wand/config.go:118.3,118.22 1 0 +code.squareroundforest.org/arpio/wand/config.go:118.22,120.4 1 0 +code.squareroundforest.org/arpio/wand/config.go:122.3,122.49 1 0 +code.squareroundforest.org/arpio/wand/config.go:125.2,125.15 1 0 +code.squareroundforest.org/arpio/wand/config.go:128.81,130.30 2 0 +code.squareroundforest.org/arpio/wand/config.go:130.30,132.3 1 0 +code.squareroundforest.org/arpio/wand/config.go:134.2,135.31 2 0 +code.squareroundforest.org/arpio/wand/config.go:135.31,136.25 1 0 +code.squareroundforest.org/arpio/wand/config.go:136.25,137.12 1 0 +code.squareroundforest.org/arpio/wand/config.go:140.3,140.46 1 0 +code.squareroundforest.org/arpio/wand/config.go:140.46,140.80 1 0 +code.squareroundforest.org/arpio/wand/config.go:143.2,143.46 1 0 +code.squareroundforest.org/arpio/wand/config.go:146.76,148.32 2 1 +code.squareroundforest.org/arpio/wand/config.go:148.32,150.17 2 0 +code.squareroundforest.org/arpio/wand/config.go:150.17,152.4 1 0 +code.squareroundforest.org/arpio/wand/config.go:154.3,154.21 1 0 +code.squareroundforest.org/arpio/wand/config.go:157.2,158.23 2 1 +code.squareroundforest.org/arpio/wand/config.go:158.23,159.32 1 0 +code.squareroundforest.org/arpio/wand/config.go:159.32,161.4 1 0 +code.squareroundforest.org/arpio/wand/config.go:163.3,163.39 1 0 +code.squareroundforest.org/arpio/wand/config.go:163.39,164.24 1 0 +code.squareroundforest.org/arpio/wand/config.go:164.24,166.5 1 0 +code.squareroundforest.org/arpio/wand/config.go:168.4,168.28 1 0 +code.squareroundforest.org/arpio/wand/config.go:172.2,172.16 1 1 +code.squareroundforest.org/arpio/wand/config.go:175.71,176.41 1 1 +code.squareroundforest.org/arpio/wand/config.go:176.41,178.3 1 0 +code.squareroundforest.org/arpio/wand/config.go:180.2,180.21 1 1 +code.squareroundforest.org/arpio/wand/config.go:180.21,182.3 1 0 +code.squareroundforest.org/arpio/wand/config.go:184.2,184.39 1 1 +code.squareroundforest.org/arpio/wand/config.go:187.44,188.21 1 1 +code.squareroundforest.org/arpio/wand/config.go:188.21,190.3 1 0 +code.squareroundforest.org/arpio/wand/config.go:192.2,192.31 1 1 +code.squareroundforest.org/arpio/wand/config.go:192.31,193.29 1 0 +code.squareroundforest.org/arpio/wand/config.go:193.29,195.4 1 0 +code.squareroundforest.org/arpio/wand/config.go:198.2,198.14 1 1 +code.squareroundforest.org/arpio/wand/docreflect.gen.go:5.13,64.2 58 1 +code.squareroundforest.org/arpio/wand/env.go:13.39,20.30 2 0 +code.squareroundforest.org/arpio/wand/env.go:20.30,21.13 1 0 +code.squareroundforest.org/arpio/wand/env.go:21.13,24.12 3 0 +code.squareroundforest.org/arpio/wand/env.go:27.3,27.16 1 0 +code.squareroundforest.org/arpio/wand/env.go:27.16,29.12 2 0 +code.squareroundforest.org/arpio/wand/env.go:32.3,32.15 1 0 +code.squareroundforest.org/arpio/wand/env.go:32.15,35.12 3 0 +code.squareroundforest.org/arpio/wand/env.go:38.3,38.31 1 0 +code.squareroundforest.org/arpio/wand/env.go:41.2,42.15 2 0 code.squareroundforest.org/arpio/wand/env.go:45.50,52.26 3 1 code.squareroundforest.org/arpio/wand/env.go:52.26,54.22 2 1 code.squareroundforest.org/arpio/wand/env.go:54.22,55.12 1 1 -code.squareroundforest.org/arpio/wand/env.go:58.3,60.73 3 1 -code.squareroundforest.org/arpio/wand/env.go:60.73,61.12 1 1 -code.squareroundforest.org/arpio/wand/env.go:64.3,66.39 3 1 +code.squareroundforest.org/arpio/wand/env.go:58.3,60.73 3 0 +code.squareroundforest.org/arpio/wand/env.go:60.73,61.12 1 0 +code.squareroundforest.org/arpio/wand/env.go:64.3,66.39 3 0 code.squareroundforest.org/arpio/wand/env.go:69.2,69.10 1 1 -code.squareroundforest.org/arpio/wand/exec.go:11.82,15.45 4 1 -code.squareroundforest.org/arpio/wand/exec.go:15.45,16.13 1 0 -code.squareroundforest.org/arpio/wand/exec.go:19.2,22.21 4 1 -code.squareroundforest.org/arpio/wand/exec.go:22.21,27.3 4 0 -code.squareroundforest.org/arpio/wand/exec.go:29.5,29.26 1 1 -code.squareroundforest.org/arpio/wand/exec.go:29.26,32.6 2 0 -code.squareroundforest.org/arpio/wand/exec.go:34.2,36.39 3 1 -code.squareroundforest.org/arpio/wand/exec.go:36.39,39.6 2 0 -code.squareroundforest.org/arpio/wand/exec.go:41.2,41.50 1 1 -code.squareroundforest.org/arpio/wand/exec.go:41.50,46.3 4 1 -code.squareroundforest.org/arpio/wand/exec.go:48.2,49.16 2 1 -code.squareroundforest.org/arpio/wand/exec.go:49.16,53.3 3 0 -code.squareroundforest.org/arpio/wand/exec.go:55.2,55.52 1 1 -code.squareroundforest.org/arpio/wand/exec.go:55.52,59.3 3 0 -code.squareroundforest.org/arpio/wand/help.go:9.17,14.2 1 1 -code.squareroundforest.org/arpio/wand/help.go:16.30,18.40 2 1 -code.squareroundforest.org/arpio/wand/help.go:18.40,20.31 2 1 -code.squareroundforest.org/arpio/wand/help.go:20.31,22.10 1 0 -code.squareroundforest.org/arpio/wand/help.go:25.5,25.20 1 1 -code.squareroundforest.org/arpio/wand/help.go:25.20,27.6 1 1 -code.squareroundforest.org/arpio/wand/help.go:29.5,29.15 1 1 -code.squareroundforest.org/arpio/wand/help.go:32.38,33.40 1 1 -code.squareroundforest.org/arpio/wand/help.go:33.40,34.22 1 1 -code.squareroundforest.org/arpio/wand/help.go:34.22,36.10 1 1 -code.squareroundforest.org/arpio/wand/help.go:39.5,39.17 1 0 -code.squareroundforest.org/arpio/wand/help.go:42.40,46.2 3 0 -code.squareroundforest.org/arpio/wand/help.go:48.64,49.31 1 1 -code.squareroundforest.org/arpio/wand/help.go:49.31,52.6 2 1 -code.squareroundforest.org/arpio/wand/help.go:54.5,54.34 1 0 -code.squareroundforest.org/arpio/wand/help.go:54.34,57.6 2 0 -code.squareroundforest.org/arpio/wand/help.go:60.62,61.2 0 0 -code.squareroundforest.org/arpio/wand/input.go:8.40,10.37 2 1 -code.squareroundforest.org/arpio/wand/input.go:10.37,12.10 2 1 -code.squareroundforest.org/arpio/wand/input.go:12.10,13.12 1 0 -code.squareroundforest.org/arpio/wand/input.go:16.3,16.24 1 1 -code.squareroundforest.org/arpio/wand/input.go:16.24,17.46 1 1 -code.squareroundforest.org/arpio/wand/input.go:17.46,23.5 1 0 -code.squareroundforest.org/arpio/wand/input.go:25.4,25.29 1 1 -code.squareroundforest.org/arpio/wand/input.go:25.29,26.28 1 1 -code.squareroundforest.org/arpio/wand/input.go:26.28,31.6 1 1 -code.squareroundforest.org/arpio/wand/input.go:36.2,36.12 1 1 -code.squareroundforest.org/arpio/wand/input.go:39.49,42.46 3 1 -code.squareroundforest.org/arpio/wand/input.go:42.46,46.3 3 1 -code.squareroundforest.org/arpio/wand/input.go:48.2,49.23 2 1 -code.squareroundforest.org/arpio/wand/input.go:49.23,51.42 2 1 -code.squareroundforest.org/arpio/wand/input.go:51.42,53.4 1 1 -code.squareroundforest.org/arpio/wand/input.go:55.3,55.28 1 1 -code.squareroundforest.org/arpio/wand/input.go:58.2,59.24 2 1 -code.squareroundforest.org/arpio/wand/input.go:59.24,61.24 2 1 -code.squareroundforest.org/arpio/wand/input.go:61.24,63.27 2 1 -code.squareroundforest.org/arpio/wand/input.go:63.27,65.5 1 1 -code.squareroundforest.org/arpio/wand/input.go:67.4,67.42 1 1 -code.squareroundforest.org/arpio/wand/input.go:67.42,73.5 1 0 -code.squareroundforest.org/arpio/wand/input.go:75.4,75.26 1 1 -code.squareroundforest.org/arpio/wand/input.go:75.26,76.57 1 1 -code.squareroundforest.org/arpio/wand/input.go:76.57,81.6 1 1 -code.squareroundforest.org/arpio/wand/input.go:83.5,83.59 1 1 -code.squareroundforest.org/arpio/wand/input.go:83.59,88.6 1 0 -code.squareroundforest.org/arpio/wand/input.go:93.2,93.12 1 1 -code.squareroundforest.org/arpio/wand/input.go:96.56,104.18 8 1 -code.squareroundforest.org/arpio/wand/input.go:104.18,107.3 2 1 -code.squareroundforest.org/arpio/wand/input.go:109.2,109.29 1 1 -code.squareroundforest.org/arpio/wand/input.go:109.29,111.3 1 0 -code.squareroundforest.org/arpio/wand/input.go:113.2,113.27 1 1 -code.squareroundforest.org/arpio/wand/input.go:113.27,115.3 1 0 -code.squareroundforest.org/arpio/wand/input.go:117.2,117.18 1 1 -code.squareroundforest.org/arpio/wand/input.go:117.18,119.3 1 0 -code.squareroundforest.org/arpio/wand/input.go:121.2,121.30 1 1 -code.squareroundforest.org/arpio/wand/input.go:121.30,123.3 1 0 -code.squareroundforest.org/arpio/wand/input.go:125.2,125.23 1 1 -code.squareroundforest.org/arpio/wand/input.go:125.23,127.18 2 1 -code.squareroundforest.org/arpio/wand/input.go:127.18,129.4 1 1 -code.squareroundforest.org/arpio/wand/input.go:129.9,131.4 1 1 -code.squareroundforest.org/arpio/wand/input.go:133.3,133.23 1 1 -code.squareroundforest.org/arpio/wand/input.go:133.23,139.4 1 0 -code.squareroundforest.org/arpio/wand/input.go:142.2,142.12 1 1 -code.squareroundforest.org/arpio/wand/input.go:145.58,146.44 1 1 -code.squareroundforest.org/arpio/wand/input.go:146.44,148.3 1 1 -code.squareroundforest.org/arpio/wand/input.go:150.2,150.57 1 1 -code.squareroundforest.org/arpio/wand/input.go:150.57,152.3 1 1 -code.squareroundforest.org/arpio/wand/input.go:154.2,154.67 1 1 -code.squareroundforest.org/arpio/wand/input.go:154.67,156.3 1 0 -code.squareroundforest.org/arpio/wand/input.go:158.2,158.12 1 1 -code.squareroundforest.org/arpio/wand/output.go:8.46,9.23 1 1 -code.squareroundforest.org/arpio/wand/output.go:9.23,11.9 2 1 -code.squareroundforest.org/arpio/wand/output.go:11.9,12.43 1 0 -code.squareroundforest.org/arpio/wand/output.go:12.43,14.5 1 0 -code.squareroundforest.org/arpio/wand/output.go:16.4,16.12 1 0 -code.squareroundforest.org/arpio/wand/output.go:19.3,19.55 1 1 -code.squareroundforest.org/arpio/wand/output.go:19.55,21.4 1 0 -code.squareroundforest.org/arpio/wand/output.go:24.2,24.12 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:20.58,21.19 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:21.19,23.3 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:25.2,25.33 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:25.33,30.3 4 0 -code.squareroundforest.org/arpio/wand/reflect.go:32.2,35.10 4 0 -code.squareroundforest.org/arpio/wand/reflect.go:38.37,39.18 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:41.17,42.26 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:43.10,44.11 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:48.36,51.2 2 1 -code.squareroundforest.org/arpio/wand/reflect.go:53.45,54.18 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:55.20,57.20 2 0 -code.squareroundforest.org/arpio/wand/reflect.go:58.78,60.20 2 1 -code.squareroundforest.org/arpio/wand/reflect.go:61.83,63.20 2 0 -code.squareroundforest.org/arpio/wand/reflect.go:64.40,66.20 2 0 -code.squareroundforest.org/arpio/wand/reflect.go:67.22,68.14 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:69.10,70.15 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:74.41,76.18 2 1 -code.squareroundforest.org/arpio/wand/reflect.go:77.20,79.46 2 0 -code.squareroundforest.org/arpio/wand/reflect.go:80.78,82.46 2 1 -code.squareroundforest.org/arpio/wand/reflect.go:83.83,85.46 2 0 -code.squareroundforest.org/arpio/wand/reflect.go:86.40,88.46 2 0 -code.squareroundforest.org/arpio/wand/reflect.go:89.10,90.46 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:93.2,93.29 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:96.40,97.17 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:97.17,99.3 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:101.2,106.39 2 1 -code.squareroundforest.org/arpio/wand/reflect.go:106.39,113.21 7 1 -code.squareroundforest.org/arpio/wand/reflect.go:127.19,128.86 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:129.26,130.28 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:130.28,132.5 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:133.23,135.20 2 0 -code.squareroundforest.org/arpio/wand/reflect.go:135.20,137.5 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:137.10,138.24 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:138.24,141.6 2 0 -code.squareroundforest.org/arpio/wand/reflect.go:143.5,143.46 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:148.2,149.32 2 1 -code.squareroundforest.org/arpio/wand/reflect.go:149.32,151.3 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:153.2,153.33 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:153.33,155.3 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:157.2,158.24 2 1 -code.squareroundforest.org/arpio/wand/reflect.go:158.24,160.3 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:162.2,162.39 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:165.36,167.23 2 1 -code.squareroundforest.org/arpio/wand/reflect.go:167.23,168.36 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:168.36,170.4 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:173.2,173.10 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:176.45,183.23 7 1 -code.squareroundforest.org/arpio/wand/reflect.go:183.23,185.3 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:187.2,187.11 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:190.81,192.33 2 1 -code.squareroundforest.org/arpio/wand/reflect.go:192.33,195.11 3 1 -code.squareroundforest.org/arpio/wand/reflect.go:195.11,197.4 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:200.2,200.10 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:203.58,204.55 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:204.55,206.3 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:209.54,210.55 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:210.55,212.3 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:215.46,216.16 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:216.16,218.3 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:220.2,222.19 3 0 -code.squareroundforest.org/arpio/wand/reflect.go:223.20,224.35 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:225.78,226.20 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:227.79,228.15 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:229.11,230.16 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:232.83,233.20 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:234.84,235.15 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:236.11,237.16 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:239.40,240.20 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:241.41,242.15 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:243.11,244.16 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:246.22,247.37 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:248.25,249.86 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:250.10,251.15 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:255.43,256.31 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:256.31,258.3 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:260.2,260.18 1 1 -code.squareroundforest.org/arpio/wand/reflect.go:261.38,262.35 1 0 -code.squareroundforest.org/arpio/wand/reflect.go:263.10,264.15 1 1 -code.squareroundforest.org/arpio/wand/wand.go:17.57,19.2 1 1 -code.squareroundforest.org/arpio/wand/wand.go:21.27,24.2 2 1 -code.squareroundforest.org/arpio/wand/wand.go:26.39,31.2 4 0 -code.squareroundforest.org/arpio/wand/wand.go:33.43,37.2 3 1 -code.squareroundforest.org/arpio/wand/wand.go:39.21,42.2 2 0 +code.squareroundforest.org/arpio/wand/exec.go:12.112,15.51 3 1 +code.squareroundforest.org/arpio/wand/exec.go:15.51,19.3 3 1 +code.squareroundforest.org/arpio/wand/exec.go:21.2,21.40 1 1 +code.squareroundforest.org/arpio/wand/exec.go:21.40,22.56 1 0 +code.squareroundforest.org/arpio/wand/exec.go:22.56,25.4 2 0 +code.squareroundforest.org/arpio/wand/exec.go:27.3,27.9 1 0 +code.squareroundforest.org/arpio/wand/exec.go:30.2,30.45 1 1 +code.squareroundforest.org/arpio/wand/exec.go:30.45,32.68 2 0 +code.squareroundforest.org/arpio/wand/exec.go:32.68,35.4 2 0 +code.squareroundforest.org/arpio/wand/exec.go:37.3,37.9 1 0 +code.squareroundforest.org/arpio/wand/exec.go:40.2,42.16 3 1 +code.squareroundforest.org/arpio/wand/exec.go:42.16,43.62 1 0 +code.squareroundforest.org/arpio/wand/exec.go:43.62,46.4 2 0 +code.squareroundforest.org/arpio/wand/exec.go:48.3,48.9 1 0 +code.squareroundforest.org/arpio/wand/exec.go:51.2,51.23 1 1 +code.squareroundforest.org/arpio/wand/exec.go:51.23,52.50 1 0 +code.squareroundforest.org/arpio/wand/exec.go:52.50,55.4 2 0 +code.squareroundforest.org/arpio/wand/exec.go:57.3,57.9 1 0 +code.squareroundforest.org/arpio/wand/exec.go:60.2,61.21 2 1 +code.squareroundforest.org/arpio/wand/exec.go:61.21,63.3 1 1 +code.squareroundforest.org/arpio/wand/exec.go:65.2,66.36 2 1 +code.squareroundforest.org/arpio/wand/exec.go:66.36,67.62 1 0 +code.squareroundforest.org/arpio/wand/exec.go:67.62,70.4 2 0 +code.squareroundforest.org/arpio/wand/exec.go:72.3,72.9 1 0 +code.squareroundforest.org/arpio/wand/exec.go:75.2,75.21 1 1 +code.squareroundforest.org/arpio/wand/exec.go:75.21,80.3 4 0 +code.squareroundforest.org/arpio/wand/exec.go:82.2,83.16 2 1 +code.squareroundforest.org/arpio/wand/exec.go:83.16,87.3 3 0 +code.squareroundforest.org/arpio/wand/exec.go:89.2,89.59 1 1 +code.squareroundforest.org/arpio/wand/exec.go:89.59,94.3 4 1 +code.squareroundforest.org/arpio/wand/exec.go:96.2,97.16 2 1 +code.squareroundforest.org/arpio/wand/exec.go:97.16,101.3 3 0 +code.squareroundforest.org/arpio/wand/exec.go:103.2,103.52 1 1 +code.squareroundforest.org/arpio/wand/exec.go:103.52,107.3 3 0 +code.squareroundforest.org/arpio/wand/format.go:10.114,12.39 2 0 +code.squareroundforest.org/arpio/wand/format.go:12.39,13.17 1 0 +code.squareroundforest.org/arpio/wand/format.go:13.17,15.4 1 0 +code.squareroundforest.org/arpio/wand/format.go:17.3,17.40 1 0 +code.squareroundforest.org/arpio/wand/format.go:20.2,20.30 1 0 +code.squareroundforest.org/arpio/wand/format.go:20.30,21.17 1 0 +code.squareroundforest.org/arpio/wand/format.go:21.17,23.4 1 0 +code.squareroundforest.org/arpio/wand/format.go:25.3,25.38 1 0 +code.squareroundforest.org/arpio/wand/format.go:28.2,28.24 1 0 +code.squareroundforest.org/arpio/wand/format.go:28.24,30.3 1 0 +code.squareroundforest.org/arpio/wand/format.go:32.2,32.8 1 0 +code.squareroundforest.org/arpio/wand/format.go:35.34,42.19 3 0 +code.squareroundforest.org/arpio/wand/format.go:42.19,44.17 2 0 +code.squareroundforest.org/arpio/wand/format.go:44.17,45.26 1 0 +code.squareroundforest.org/arpio/wand/format.go:45.26,47.5 1 0 +code.squareroundforest.org/arpio/wand/format.go:49.4,49.12 1 0 +code.squareroundforest.org/arpio/wand/format.go:52.3,52.38 1 0 +code.squareroundforest.org/arpio/wand/format.go:55.2,55.24 1 0 +code.squareroundforest.org/arpio/wand/format.go:55.24,57.3 1 0 +code.squareroundforest.org/arpio/wand/format.go:59.2,60.31 2 0 +code.squareroundforest.org/arpio/wand/format.go:60.31,62.3 1 0 +code.squareroundforest.org/arpio/wand/format.go:64.2,64.42 1 0 +code.squareroundforest.org/arpio/wand/format.go:67.29,71.2 3 0 +code.squareroundforest.org/arpio/wand/format.go:73.37,76.20 3 0 +code.squareroundforest.org/arpio/wand/format.go:76.20,78.3 1 0 +code.squareroundforest.org/arpio/wand/format.go:80.2,80.31 1 0 +code.squareroundforest.org/arpio/wand/format.go:83.32,86.20 3 0 +code.squareroundforest.org/arpio/wand/format.go:86.20,88.3 1 0 +code.squareroundforest.org/arpio/wand/format.go:90.2,90.31 1 0 +code.squareroundforest.org/arpio/wand/format.go:93.85,94.23 1 0 +code.squareroundforest.org/arpio/wand/format.go:94.23,96.36 2 0 +code.squareroundforest.org/arpio/wand/format.go:96.36,98.4 1 0 +code.squareroundforest.org/arpio/wand/format.go:100.3,101.16 2 0 +code.squareroundforest.org/arpio/wand/format.go:101.16,103.4 1 0 +code.squareroundforest.org/arpio/wand/format.go:105.3,105.25 1 0 +code.squareroundforest.org/arpio/wand/format.go:105.25,107.4 1 0 +code.squareroundforest.org/arpio/wand/format.go:109.3,110.26 2 0 +code.squareroundforest.org/arpio/wand/format.go:110.26,112.4 1 0 +code.squareroundforest.org/arpio/wand/format.go:114.3,114.35 1 0 +code.squareroundforest.org/arpio/wand/format.go:117.2,118.8 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:11.38,13.19 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:13.19,14.67 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:14.67,16.4 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:18.3,18.35 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:18.35,20.4 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:23.2,23.18 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:26.47,30.58 4 0 +code.squareroundforest.org/arpio/wand/formathelp.go:30.58,34.3 3 0 +code.squareroundforest.org/arpio/wand/formathelp.go:36.2,36.27 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:36.27,39.30 3 0 +code.squareroundforest.org/arpio/wand/formathelp.go:39.30,41.4 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:43.3,43.50 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:43.50,45.4 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:47.3,47.38 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:47.38,51.11 4 0 +code.squareroundforest.org/arpio/wand/formathelp.go:52.28,53.71 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:54.17,55.55 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:56.17,57.55 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:61.3,61.12 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:64.2,64.33 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:64.33,71.3 6 0 +code.squareroundforest.org/arpio/wand/formathelp.go:73.2,73.27 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:73.27,77.3 3 0 +code.squareroundforest.org/arpio/wand/formathelp.go:79.2,79.26 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:79.26,82.47 3 0 +code.squareroundforest.org/arpio/wand/formathelp.go:82.47,84.26 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:84.26,87.5 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:89.4,89.26 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:89.26,92.5 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:95.3,100.27 5 0 +code.squareroundforest.org/arpio/wand/formathelp.go:100.27,101.20 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:101.20,103.5 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:106.3,106.24 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:106.24,109.4 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:111.3,111.27 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:111.27,113.19 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:113.19,115.5 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:117.4,117.13 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:121.2,121.30 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:121.30,129.38 7 0 +code.squareroundforest.org/arpio/wand/formathelp.go:129.38,131.20 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:131.20,133.5 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:135.4,136.17 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:136.17,138.5 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:140.4,140.28 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:140.28,142.5 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:142.10,142.31 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:142.31,144.5 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:146.4,146.16 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:149.3,152.27 3 0 +code.squareroundforest.org/arpio/wand/formathelp.go:152.27,153.20 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:153.20,155.5 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:158.3,158.24 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:158.24,161.4 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:163.3,163.27 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:163.27,165.19 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:165.19,167.5 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:169.4,169.13 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:173.2,173.76 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:173.76,185.15 12 0 +code.squareroundforest.org/arpio/wand/formathelp.go:185.15,187.4 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:187.9,189.4 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:191.3,191.12 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:194.2,194.54 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:194.54,203.38 9 0 +code.squareroundforest.org/arpio/wand/formathelp.go:203.38,204.21 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:204.21,207.13 3 0 +code.squareroundforest.org/arpio/wand/formathelp.go:210.4,210.19 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:210.19,212.20 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:212.20,214.6 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:216.5,217.13 2 0 +code.squareroundforest.org/arpio/wand/formathelp.go:221.3,232.15 12 0 +code.squareroundforest.org/arpio/wand/formathelp.go:232.15,234.4 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:234.9,236.4 1 0 +code.squareroundforest.org/arpio/wand/formathelp.go:238.3,246.12 9 0 +code.squareroundforest.org/arpio/wand/formathelp.go:249.2,249.17 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:11.34,18.23 3 0 +code.squareroundforest.org/arpio/wand/formatman.go:18.23,19.13 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:20.23,21.29 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:22.18,23.19 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:23.19,25.5 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:27.4,27.23 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:28.15,29.39 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:30.15,31.39 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:32.15,33.39 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:34.15,35.39 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:36.15,37.39 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:38.15,39.39 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:40.11,41.23 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:44.3,44.27 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:47.2,47.19 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:50.83,53.29 3 0 +code.squareroundforest.org/arpio/wand/formatman.go:53.29,55.3 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:57.2,57.49 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:57.49,59.3 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:61.2,63.37 3 0 +code.squareroundforest.org/arpio/wand/formatman.go:63.37,65.25 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:65.25,67.4 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:69.3,69.10 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:70.27,71.70 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:72.16,73.54 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:74.16,75.54 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:79.2,79.33 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:79.33,80.25 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:80.25,82.4 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:84.3,84.38 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:84.38,85.13 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:85.13,87.5 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:89.4,89.52 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:93.2,93.27 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:93.27,96.3 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:98.2,98.26 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:98.26,100.47 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:100.47,102.4 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:104.3,104.25 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:104.25,107.4 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:109.3,109.25 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:109.25,110.26 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:110.26,112.5 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:114.4,115.60 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:118.3,119.27 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:119.27,123.4 3 0 +code.squareroundforest.org/arpio/wand/formatman.go:126.2,126.76 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:126.76,134.15 8 0 +code.squareroundforest.org/arpio/wand/formatman.go:134.15,136.4 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:136.9,138.4 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:140.3,140.12 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:143.2,143.54 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:143.54,147.38 4 0 +code.squareroundforest.org/arpio/wand/formatman.go:147.38,148.13 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:148.13,150.5 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:152.4,152.21 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:152.21,154.13 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:157.4,157.19 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:157.19,159.20 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:159.20,161.6 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:163.5,164.13 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:168.3,175.15 8 0 +code.squareroundforest.org/arpio/wand/formatman.go:175.15,177.4 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:177.9,179.4 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:181.3,186.47 6 0 +code.squareroundforest.org/arpio/wand/formatman.go:190.58,197.32 7 0 +code.squareroundforest.org/arpio/wand/formatman.go:197.32,198.12 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:198.12,200.4 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:202.3,202.37 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:205.2,205.32 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:205.32,208.3 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:210.2,210.17 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:213.59,219.2 5 0 +code.squareroundforest.org/arpio/wand/formatman.go:221.46,223.37 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:223.37,224.34 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:224.34,225.12 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:228.3,229.8 2 0 +code.squareroundforest.org/arpio/wand/formatman.go:232.2,232.20 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:232.20,234.3 1 0 +code.squareroundforest.org/arpio/wand/formatman.go:236.2,236.41 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:10.31,13.2 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:15.32,22.23 3 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:22.23,23.13 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:24.68,25.29 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:26.12,27.17 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:27.17,29.5 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:31.4,31.23 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:32.11,34.34 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:38.2,38.19 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:41.99,45.29 4 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:45.29,47.3 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:49.2,49.49 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:49.49,51.3 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:53.2,53.37 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:53.37,55.3 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:57.2,62.37 5 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:62.37,63.25 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:63.25,65.4 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:67.3,67.10 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:68.27,69.70 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:70.16,71.54 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:72.16,73.54 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:77.2,77.33 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:77.33,80.38 3 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:80.38,82.4 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:84.3,84.17 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:87.2,87.27 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:87.27,90.3 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:92.2,92.26 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:92.26,94.25 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:94.25,96.4 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:98.3,98.25 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:98.25,100.4 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:102.3,102.47 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:102.47,104.4 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:106.3,107.27 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:107.27,109.4 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:112.2,112.76 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:112.76,122.15 10 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:122.15,124.4 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:124.9,126.4 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:128.3,129.17 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:132.2,132.54 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:132.54,138.38 6 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:138.38,139.21 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:139.21,141.13 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:144.4,144.19 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:144.19,146.20 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:146.20,148.6 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:150.5,151.13 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:155.3,163.15 9 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:163.15,165.4 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:165.9,167.4 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:169.3,177.17 9 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:181.74,187.32 6 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:187.32,189.3 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:191.2,192.32 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:192.32,195.3 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:197.2,197.17 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:200.75,205.2 4 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:207.62,209.37 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:209.37,210.34 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:210.34,211.12 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:214.3,215.8 2 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:218.2,218.20 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:218.20,220.3 1 0 +code.squareroundforest.org/arpio/wand/formatmarkdown.go:222.2,222.53 1 0 +code.squareroundforest.org/arpio/wand/help.go:68.17,73.2 1 1 +code.squareroundforest.org/arpio/wand/help.go:75.30,77.37 2 1 +code.squareroundforest.org/arpio/wand/help.go:77.37,79.25 2 0 +code.squareroundforest.org/arpio/wand/help.go:79.25,81.4 1 0 +code.squareroundforest.org/arpio/wand/help.go:84.2,84.38 1 1 +code.squareroundforest.org/arpio/wand/help.go:84.38,86.3 1 1 +code.squareroundforest.org/arpio/wand/help.go:88.2,88.12 1 1 +code.squareroundforest.org/arpio/wand/help.go:91.38,92.37 1 1 +code.squareroundforest.org/arpio/wand/help.go:92.37,93.16 1 1 +code.squareroundforest.org/arpio/wand/help.go:93.16,95.4 1 1 +code.squareroundforest.org/arpio/wand/help.go:98.2,98.14 1 0 +code.squareroundforest.org/arpio/wand/help.go:101.40,102.21 1 0 +code.squareroundforest.org/arpio/wand/help.go:102.21,104.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:106.2,108.12 3 0 +code.squareroundforest.org/arpio/wand/help.go:111.64,112.28 1 1 +code.squareroundforest.org/arpio/wand/help.go:112.28,115.3 2 1 +code.squareroundforest.org/arpio/wand/help.go:117.2,117.31 1 0 +code.squareroundforest.org/arpio/wand/help.go:117.31,120.3 2 0 +code.squareroundforest.org/arpio/wand/help.go:123.31,124.21 1 0 +code.squareroundforest.org/arpio/wand/help.go:124.21,126.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:128.2,132.30 5 0 +code.squareroundforest.org/arpio/wand/help.go:135.33,137.37 2 0 +code.squareroundforest.org/arpio/wand/help.go:137.37,139.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:141.2,141.43 1 0 +code.squareroundforest.org/arpio/wand/help.go:141.43,143.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:145.2,145.17 1 0 +code.squareroundforest.org/arpio/wand/help.go:148.59,150.25 2 0 +code.squareroundforest.org/arpio/wand/help.go:150.25,152.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:154.2,154.14 1 0 +code.squareroundforest.org/arpio/wand/help.go:157.46,158.21 1 0 +code.squareroundforest.org/arpio/wand/help.go:158.21,160.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:162.2,168.24 7 0 +code.squareroundforest.org/arpio/wand/help.go:168.24,170.30 2 0 +code.squareroundforest.org/arpio/wand/help.go:170.30,172.4 1 0 +code.squareroundforest.org/arpio/wand/help.go:175.2,183.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:186.64,193.2 1 0 +code.squareroundforest.org/arpio/wand/help.go:195.43,196.23 1 0 +code.squareroundforest.org/arpio/wand/help.go:196.23,198.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:200.2,200.21 1 0 +code.squareroundforest.org/arpio/wand/help.go:200.21,202.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:204.2,204.74 1 0 +code.squareroundforest.org/arpio/wand/help.go:207.70,208.21 1 0 +code.squareroundforest.org/arpio/wand/help.go:208.21,210.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:212.2,213.46 2 0 +code.squareroundforest.org/arpio/wand/help.go:213.46,216.3 2 0 +code.squareroundforest.org/arpio/wand/help.go:218.2,221.23 4 0 +code.squareroundforest.org/arpio/wand/help.go:221.23,223.24 2 0 +code.squareroundforest.org/arpio/wand/help.go:223.24,225.4 1 0 +code.squareroundforest.org/arpio/wand/help.go:228.2,230.26 3 0 +code.squareroundforest.org/arpio/wand/help.go:230.26,238.26 2 0 +code.squareroundforest.org/arpio/wand/help.go:238.26,239.27 1 0 +code.squareroundforest.org/arpio/wand/help.go:239.27,241.5 1 0 +code.squareroundforest.org/arpio/wand/help.go:244.3,244.21 1 0 +code.squareroundforest.org/arpio/wand/help.go:247.2,247.25 1 0 +code.squareroundforest.org/arpio/wand/help.go:247.25,254.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:256.2,256.10 1 0 +code.squareroundforest.org/arpio/wand/help.go:259.60,261.22 2 0 +code.squareroundforest.org/arpio/wand/help.go:261.22,264.3 2 0 +code.squareroundforest.org/arpio/wand/help.go:266.2,266.21 1 0 +code.squareroundforest.org/arpio/wand/help.go:266.21,269.3 2 0 +code.squareroundforest.org/arpio/wand/help.go:271.2,271.31 1 0 +code.squareroundforest.org/arpio/wand/help.go:271.31,273.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:275.2,275.13 1 0 +code.squareroundforest.org/arpio/wand/help.go:278.67,282.37 3 0 +code.squareroundforest.org/arpio/wand/help.go:282.37,284.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:286.2,288.28 3 0 +code.squareroundforest.org/arpio/wand/help.go:288.28,289.15 1 0 +code.squareroundforest.org/arpio/wand/help.go:289.15,291.4 1 0 +code.squareroundforest.org/arpio/wand/help.go:293.3,293.24 1 0 +code.squareroundforest.org/arpio/wand/help.go:293.24,295.4 1 0 +code.squareroundforest.org/arpio/wand/help.go:298.2,317.3 1 0 +code.squareroundforest.org/arpio/wand/help.go:320.80,323.2 2 0 +code.squareroundforest.org/arpio/wand/help.go:325.61,328.2 2 0 +code.squareroundforest.org/arpio/wand/help.go:330.77,333.2 2 0 +code.squareroundforest.org/arpio/wand/help.go:335.48,338.2 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:44.40,46.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:47.35,49.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:50.46,52.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:53.73,54.27 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:54.27,55.17 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:55.17,57.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:59.2,59.28 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:59.28,60.37 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:60.37,62.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:64.2,64.12 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:66.41,68.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:69.40,70.48 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:70.48,71.30 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:71.30,74.4 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:75.3,76.9 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:78.2,78.25 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:80.41,82.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:83.36,85.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:86.57,88.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:109.44,111.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:112.39,114.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:115.50,117.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:118.44,119.17 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:119.17,120.40 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:120.40,123.4 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:124.3,124.40 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:126.2,133.31 5 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:133.31,135.19 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:135.19,136.46 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:136.46,139.13 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:141.4,142.24 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:142.24,143.26 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:143.26,146.6 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:147.5,147.20 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:147.20,149.6 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:150.5,150.11 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:152.4,152.113 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:152.113,154.5 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:155.4,156.19 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:156.19,158.5 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:159.4,159.10 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:161.3,162.13 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:162.13,164.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:165.3,166.86 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:166.86,169.4 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:171.2,171.54 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:171.54,172.112 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:172.112,174.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:175.3,176.18 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:176.18,178.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:179.3,179.9 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:181.2,181.38 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:181.38,182.33 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:182.33,184.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:186.2,186.23 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:186.23,189.3 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:190.2,192.17 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:192.17,194.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:196.45,198.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:199.40,201.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:202.61,204.9 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:204.9,206.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:207.2,209.16 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:209.16,211.26 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:211.26,213.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:214.3,214.77 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:215.8,215.19 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:215.19,217.39 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:217.39,219.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:220.8,221.40 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:221.40,223.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:224.3,225.39 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:225.39,227.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:229.2,234.31 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:234.31,237.10 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:237.10,240.12 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:242.3,242.26 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:242.26,245.76 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:245.76,248.5 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:249.4,249.12 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:251.3,251.44 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:251.44,252.61 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:252.61,254.5 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:256.3,257.19 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:259.2,259.13 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:259.13,261.39 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:261.39,263.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:265.2,265.25 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:265.25,267.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:268.2,268.90 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:286.42,288.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:289.37,291.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:292.48,294.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:295.42,296.22 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:296.22,298.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:299.2,299.39 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:299.39,302.3 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:303.2,315.6 8 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:315.6,318.36 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:318.36,321.20 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:321.20,322.34 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:322.34,325.6 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:327.4,327.47 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:327.47,329.13 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:331.4,335.38 5 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:337.3,337.18 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:337.18,338.9 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:341.2,341.11 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:341.11,342.55 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:342.55,343.113 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:343.113,345.5 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:346.4,348.10 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:350.3,350.22 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:350.22,353.4 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:353.9,353.36 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:353.36,356.4 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:356.9,359.4 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:360.3,362.9 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:364.2,364.36 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:364.36,367.130 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:367.130,369.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:371.2,373.37 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:375.43,377.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:378.38,380.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:381.59,383.9 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:383.9,385.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:386.2,388.12 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:388.12,390.39 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:390.39,392.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:393.8,394.40 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:394.40,396.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:397.3,398.39 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:398.39,400.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:402.2,403.30 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:403.30,404.53 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:404.53,406.9 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:409.2,410.13 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:410.13,412.39 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:412.39,414.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:416.2,416.25 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:416.25,418.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:419.2,419.86 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:424.36,426.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:427.29,429.21 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:429.21,430.21 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:430.21,432.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:432.9,434.37 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:434.37,436.5 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:439.2,439.26 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:441.31,443.21 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:443.21,445.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:446.2,446.27 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:448.34,450.21 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:450.21,452.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:453.2,453.35 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:462.57,463.24 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:463.24,465.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:466.2,466.24 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:466.24,469.3 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:470.2,471.39 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:471.39,473.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:474.2,474.13 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:476.57,477.23 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:477.23,479.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:480.2,480.23 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:480.23,483.3 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:484.2,485.38 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:485.38,487.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:488.2,488.12 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:490.48,492.47 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:492.47,493.61 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:493.61,494.12 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:496.3,496.9 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:498.2,498.51 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:500.46,501.27 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:501.27,502.48 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:502.48,503.32 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:503.32,504.13 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:506.4,506.10 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:509.2,510.30 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:510.30,512.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:513.2,513.27 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:515.55,516.28 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:516.28,518.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:519.2,519.47 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:519.47,520.31 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:520.31,521.12 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:523.3,523.33 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:523.33,525.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:527.2,527.14 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:529.60,530.28 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:530.28,532.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:533.2,535.47 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:535.47,536.31 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:536.31,537.12 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:539.3,539.32 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:539.32,541.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:542.3,542.15 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:544.2,544.18 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:546.67,547.86 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:547.86,549.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:550.2,551.19 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:553.51,554.47 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:554.47,555.31 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:555.31,556.12 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:558.3,558.33 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:558.33,561.4 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:564.34,566.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:567.48,568.28 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:568.28,570.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:571.2,571.33 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:571.33,572.35 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:572.35,574.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:576.2,576.14 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:578.47,580.33 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:580.33,581.31 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:581.31,584.4 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:586.2,586.51 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:588.49,589.33 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:589.33,590.35 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:590.35,592.9 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:613.62,615.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:616.31,617.31 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:617.31,619.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:620.2,621.16 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:621.16,622.20 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:622.20,623.14 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:623.14,626.5 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:627.9,630.4 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:632.2,633.38 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:633.38,636.3 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:637.2,638.13 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:640.40,641.31 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:641.31,643.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:644.2,644.30 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:644.30,645.16 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:645.16,647.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:649.2,649.33 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:651.46,653.9 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:653.9,655.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:656.2,656.7 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:656.7,658.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:658.8,660.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:661.2,661.13 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:663.48,666.15 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:666.15,668.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:669.2,669.32 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:669.32,672.36 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:672.36,674.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:676.2,676.14 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:678.35,681.21 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:681.21,683.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:685.36,688.2 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:689.61,691.24 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:691.24,693.24 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:693.24,696.4 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:698.2,698.8 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:700.46,703.19 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:703.19,705.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:706.2,706.28 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:706.28,708.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:709.2,710.91 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:712.52,714.15 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:714.15,716.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:717.2,718.61 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:718.61,720.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:721.2,722.11 2 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:722.11,724.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:725.2,725.22 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:725.22,727.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:728.2,728.27 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:738.32,740.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:741.32,743.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:744.30,746.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:791.38,793.2 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:794.79,797.22 3 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:797.22,799.3 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:800.2,800.43 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:800.43,801.40 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:801.40,803.4 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:804.3,804.18 1 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:806.2,809.18 4 0 +code.squareroundforest.org/arpio/wand/iniparser.gen.go:814.40,1050.2 232 0 +code.squareroundforest.org/arpio/wand/input.go:9.103,11.38 2 1 +code.squareroundforest.org/arpio/wand/input.go:11.38,13.10 2 0 +code.squareroundforest.org/arpio/wand/input.go:13.10,14.12 1 0 +code.squareroundforest.org/arpio/wand/input.go:17.3,17.24 1 0 +code.squareroundforest.org/arpio/wand/input.go:17.24,18.46 1 0 +code.squareroundforest.org/arpio/wand/input.go:18.46,24.5 1 0 +code.squareroundforest.org/arpio/wand/input.go:26.4,26.29 1 0 +code.squareroundforest.org/arpio/wand/input.go:26.29,27.28 1 0 +code.squareroundforest.org/arpio/wand/input.go:27.28,32.6 1 0 +code.squareroundforest.org/arpio/wand/input.go:37.2,37.12 1 1 +code.squareroundforest.org/arpio/wand/input.go:40.46,42.2 1 1 +code.squareroundforest.org/arpio/wand/input.go:44.40,46.2 1 1 +code.squareroundforest.org/arpio/wand/input.go:48.62,51.46 3 1 +code.squareroundforest.org/arpio/wand/input.go:51.46,55.3 3 0 +code.squareroundforest.org/arpio/wand/input.go:57.2,58.23 2 1 +code.squareroundforest.org/arpio/wand/input.go:58.23,60.42 2 1 +code.squareroundforest.org/arpio/wand/input.go:60.42,62.4 1 0 +code.squareroundforest.org/arpio/wand/input.go:64.3,64.28 1 1 +code.squareroundforest.org/arpio/wand/input.go:67.2,68.31 2 1 +code.squareroundforest.org/arpio/wand/input.go:68.31,73.3 1 0 +code.squareroundforest.org/arpio/wand/input.go:75.2,75.24 1 1 +code.squareroundforest.org/arpio/wand/input.go:75.24,77.26 2 1 +code.squareroundforest.org/arpio/wand/input.go:77.26,79.4 1 0 +code.squareroundforest.org/arpio/wand/input.go:81.3,82.18 2 1 +code.squareroundforest.org/arpio/wand/input.go:82.18,84.4 1 0 +code.squareroundforest.org/arpio/wand/input.go:86.3,86.24 1 1 +code.squareroundforest.org/arpio/wand/input.go:86.24,87.42 1 1 +code.squareroundforest.org/arpio/wand/input.go:87.42,93.5 1 0 +code.squareroundforest.org/arpio/wand/input.go:95.4,95.26 1 1 +code.squareroundforest.org/arpio/wand/input.go:95.26,96.57 1 1 +code.squareroundforest.org/arpio/wand/input.go:96.57,101.6 1 0 +code.squareroundforest.org/arpio/wand/input.go:103.5,103.59 1 1 +code.squareroundforest.org/arpio/wand/input.go:103.59,108.6 1 0 +code.squareroundforest.org/arpio/wand/input.go:113.2,113.12 1 1 +code.squareroundforest.org/arpio/wand/input.go:116.56,130.18 11 1 +code.squareroundforest.org/arpio/wand/input.go:130.18,133.3 2 0 +code.squareroundforest.org/arpio/wand/input.go:135.2,135.29 1 1 +code.squareroundforest.org/arpio/wand/input.go:135.29,137.3 1 0 +code.squareroundforest.org/arpio/wand/input.go:139.2,139.27 1 1 +code.squareroundforest.org/arpio/wand/input.go:139.27,141.3 1 0 +code.squareroundforest.org/arpio/wand/input.go:143.2,143.18 1 1 +code.squareroundforest.org/arpio/wand/input.go:143.18,145.3 1 0 +code.squareroundforest.org/arpio/wand/input.go:147.2,147.30 1 1 +code.squareroundforest.org/arpio/wand/input.go:147.30,149.3 1 0 +code.squareroundforest.org/arpio/wand/input.go:151.2,151.23 1 1 +code.squareroundforest.org/arpio/wand/input.go:151.23,152.57 1 1 +code.squareroundforest.org/arpio/wand/input.go:152.57,153.12 1 1 +code.squareroundforest.org/arpio/wand/input.go:156.3,157.18 2 1 +code.squareroundforest.org/arpio/wand/input.go:157.18,159.4 1 0 +code.squareroundforest.org/arpio/wand/input.go:159.9,161.4 1 1 +code.squareroundforest.org/arpio/wand/input.go:163.3,163.37 1 1 +code.squareroundforest.org/arpio/wand/input.go:163.37,164.12 1 1 +code.squareroundforest.org/arpio/wand/input.go:167.3,167.23 1 1 +code.squareroundforest.org/arpio/wand/input.go:167.23,173.4 1 1 +code.squareroundforest.org/arpio/wand/input.go:176.2,176.12 1 1 +code.squareroundforest.org/arpio/wand/input.go:179.81,180.47 1 1 +code.squareroundforest.org/arpio/wand/input.go:180.47,182.3 1 0 +code.squareroundforest.org/arpio/wand/input.go:184.2,184.44 1 1 +code.squareroundforest.org/arpio/wand/input.go:184.44,186.3 1 0 +code.squareroundforest.org/arpio/wand/input.go:188.2,188.63 1 1 +code.squareroundforest.org/arpio/wand/input.go:188.63,190.3 1 0 +code.squareroundforest.org/arpio/wand/input.go:192.2,192.67 1 1 +code.squareroundforest.org/arpio/wand/input.go:192.67,194.3 1 1 +code.squareroundforest.org/arpio/wand/input.go:196.2,196.12 1 1 +code.squareroundforest.org/arpio/wand/output.go:10.46,11.35 1 1 +code.squareroundforest.org/arpio/wand/output.go:11.35,13.3 1 0 +code.squareroundforest.org/arpio/wand/output.go:15.2,15.23 1 1 +code.squareroundforest.org/arpio/wand/output.go:15.23,17.9 2 1 +code.squareroundforest.org/arpio/wand/output.go:17.9,18.43 1 1 +code.squareroundforest.org/arpio/wand/output.go:18.43,20.5 1 0 +code.squareroundforest.org/arpio/wand/output.go:22.4,22.12 1 1 +code.squareroundforest.org/arpio/wand/output.go:25.3,26.52 2 1 +code.squareroundforest.org/arpio/wand/output.go:26.52,27.49 1 0 +code.squareroundforest.org/arpio/wand/output.go:27.49,29.5 1 0 +code.squareroundforest.org/arpio/wand/output.go:32.3,33.19 2 1 +code.squareroundforest.org/arpio/wand/output.go:49.26,50.49 1 1 +code.squareroundforest.org/arpio/wand/output.go:50.49,52.5 1 0 +code.squareroundforest.org/arpio/wand/output.go:53.11,54.54 1 0 +code.squareroundforest.org/arpio/wand/output.go:54.54,56.5 1 0 +code.squareroundforest.org/arpio/wand/output.go:58.4,58.45 1 0 +code.squareroundforest.org/arpio/wand/output.go:58.45,60.5 1 0 +code.squareroundforest.org/arpio/wand/output.go:64.2,64.12 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:30.58,31.19 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:31.19,33.3 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:35.2,35.33 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:35.33,40.3 4 1 +code.squareroundforest.org/arpio/wand/reflect.go:42.2,45.10 4 1 +code.squareroundforest.org/arpio/wand/reflect.go:48.60,49.21 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:49.21,51.3 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:53.2,53.38 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:53.38,55.3 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:57.2,57.10 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:60.36,62.2 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:64.36,66.2 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:68.36,71.2 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:73.54,75.9 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:76.34,77.45 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:78.34,79.46 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:80.33,81.45 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:82.10,83.42 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:87.56,89.9 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:90.34,91.46 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:92.34,93.47 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:94.33,95.46 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:96.10,97.43 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:101.45,102.18 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:103.20,105.20 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:106.78,108.20 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:109.83,111.20 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:112.40,114.20 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:115.22,116.14 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:117.10,118.15 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:122.41,124.18 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:125.20,127.46 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:128.78,130.46 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:131.83,133.46 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:134.40,136.46 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:137.10,138.46 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:141.2,141.29 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:144.87,145.17 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:145.17,147.3 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:149.2,154.39 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:154.39,161.21 7 1 +code.squareroundforest.org/arpio/wand/reflect.go:175.19,181.6 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:182.26,183.28 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:183.28,190.5 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:191.23,192.20 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:192.20,194.5 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:196.4,196.22 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:196.22,198.5 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:200.4,202.18 3 0 +code.squareroundforest.org/arpio/wand/reflect.go:202.18,204.5 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:206.4,206.20 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:206.20,208.5 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:208.10,209.24 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:209.24,213.6 3 0 +code.squareroundforest.org/arpio/wand/reflect.go:215.5,215.46 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:220.2,221.32 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:221.32,223.3 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:225.2,225.33 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:225.33,227.3 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:229.2,230.24 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:230.24,232.3 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:234.2,235.16 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:235.16,237.3 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:239.2,239.30 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:242.40,245.2 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:247.36,249.23 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:249.23,250.36 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:250.36,252.4 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:255.2,255.10 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:258.45,265.23 7 1 +code.squareroundforest.org/arpio/wand/reflect.go:265.23,267.3 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:269.2,269.11 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:272.81,274.33 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:274.33,277.11 3 1 +code.squareroundforest.org/arpio/wand/reflect.go:277.11,279.4 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:282.2,282.10 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:285.58,286.55 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:286.55,288.3 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:291.52,297.23 2 1 +code.squareroundforest.org/arpio/wand/reflect.go:297.23,298.10 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:299.21,300.30 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:301.21,302.30 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:306.2,306.23 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:309.54,310.55 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:310.55,312.3 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:315.46,316.16 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:316.16,318.3 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:320.2,322.19 3 0 +code.squareroundforest.org/arpio/wand/reflect.go:323.20,324.35 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:325.78,326.20 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:327.79,328.15 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:329.11,330.16 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:332.83,333.20 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:334.84,335.15 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:336.11,337.16 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:339.40,340.20 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:341.41,342.15 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:343.11,344.16 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:346.22,347.37 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:348.25,349.86 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:350.10,351.15 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:355.43,356.31 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:356.31,358.3 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:360.2,360.18 1 1 +code.squareroundforest.org/arpio/wand/reflect.go:361.38,362.35 1 0 +code.squareroundforest.org/arpio/wand/reflect.go:363.10,364.15 1 1 +code.squareroundforest.org/arpio/wand/wand.go:32.57,34.2 1 1 +code.squareroundforest.org/arpio/wand/wand.go:36.27,39.2 2 0 +code.squareroundforest.org/arpio/wand/wand.go:41.38,45.2 3 0 +code.squareroundforest.org/arpio/wand/wand.go:47.49,49.33 2 0 +code.squareroundforest.org/arpio/wand/wand.go:49.33,54.3 1 0 +code.squareroundforest.org/arpio/wand/wand.go:56.2,56.12 1 0 +code.squareroundforest.org/arpio/wand/wand.go:59.43,66.2 2 0 +code.squareroundforest.org/arpio/wand/wand.go:68.41,72.2 1 0 +code.squareroundforest.org/arpio/wand/wand.go:74.41,76.28 2 0 +code.squareroundforest.org/arpio/wand/wand.go:76.28,78.3 1 0 +code.squareroundforest.org/arpio/wand/wand.go:80.2,80.13 1 0 +code.squareroundforest.org/arpio/wand/wand.go:83.19,85.29 1 0 +code.squareroundforest.org/arpio/wand/wand.go:85.29,87.4 1 0 +code.squareroundforest.org/arpio/wand/wand.go:91.26,94.30 1 0 +code.squareroundforest.org/arpio/wand/wand.go:94.30,98.5 1 0 +code.squareroundforest.org/arpio/wand/wand.go:101.30,105.5 1 0 +code.squareroundforest.org/arpio/wand/wand.go:110.32,112.2 1 0 +code.squareroundforest.org/arpio/wand/wand.go:114.28,116.2 1 0 +code.squareroundforest.org/arpio/wand/wand.go:118.37,120.2 1 0 diff --git a/.gitignore b/.gitignore index 0355fb8..9bc182d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ iniparser.gen.go docreflect.gen.go -.bin +.build diff --git a/Makefile b/Makefile index 813284b..77727c5 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ lib: $(SOURCES) iniparser.gen.go docreflect.gen.go go build go build ./tools -build: lib wand +build: lib .build/wand check: $(SOURCES) build go test -count 1 ./... @@ -24,7 +24,7 @@ fmt: $(SOURCES) iniparser.gen.go docreflect.gen.go go fmt ./... iniparser.gen.go: ini.treerack - go run script/ini-parser/parser.go wand < ini.treerack > iniparser.gen.go || rm iniparser.gen.go + go run script/ini-parser/parser.go wand < ini.treerack > iniparser.gen.go || rm -f iniparser.gen.go docreflect.gen.go: $(SOURCES) go run script/docreflect/docs.go \ @@ -32,13 +32,19 @@ docreflect.gen.go: $(SOURCES) code.squareroundforest.org/arpio/docreflect/generate \ code.squareroundforest.org/arpio/wand/tools \ > docreflect.gen.go \ - || rm docreflect.gen.go + || rm -f docreflect.gen.go -.bin: - mkdir -p .bin +.build: + mkdir -p .build -wand: $(SOURCES) iniparser.gen.go docreflect.gen.go .bin - go build -o .bin/wand ./cmd/wand +.build/wand: $(SOURCES) iniparser.gen.go docreflect.gen.go .build + go build -o .build/wand -ldflags "-X main.version=$(shell date +%Y-%m-%d)-$(shell git rev-parse --short HEAD)" ./cmd/wand -install: wand - cp .bin/wand ~/bin +install: .build/wand + cp .build/wand ~/bin + +clean: + rm -rf .build + rm -f docreflect.gen.go + rm -f iniparser.gen.go + rm -f .cover diff --git a/apply.go b/apply.go index 41f4f93..47eda7b 100644 --- a/apply.go +++ b/apply.go @@ -176,6 +176,10 @@ func createStructArg(t reflect.Type, shortForms []string, c config, e env, o []o } func createPositional(t reflect.Type, v string) reflect.Value { + if t.Kind() == reflect.Interface { + return reflect.ValueOf(v) + } + tup := unpack(t) sv := reflect.ValueOf(scan(tup, v)) return pack(sv, t) @@ -223,7 +227,7 @@ func processResults(t reflect.Type, out []reflect.Value) ([]any, error) { var err error last := len(out) - 1 - isErrorType := t.Out(last) == reflect.TypeOf(err) + isErrorType := t.Out(last) == reflect.TypeFor[error]() if isErrorType && !out[last].IsZero() { err = out[last].Interface().(error) } diff --git a/cmd/wand/main.go b/cmd/wand/main.go index cee3655..9f2f217 100644 --- a/cmd/wand/main.go +++ b/cmd/wand/main.go @@ -5,10 +5,15 @@ import ( "code.squareroundforest.org/arpio/wand/tools" ) +var version = "dev" + func main() { docreflect := Command("docreflect", tools.Docreflect) man := Command("manpages", tools.Man) md := Command("markdown", tools.Markdown) - exec := Default(Command("exec", tools.Exec)) - Exec(Command("wand", nil, docreflect, man, md, exec), Etc(), UserConfig()) + exec := Command("exec", tools.Exec) + wand := Command("wand", nil, docreflect, man, md, Default(exec)) + wand = Version(wand, version) + conf := MergeConfig(Etc(), UserConfig()) + Exec(wand, conf) } diff --git a/command.go b/command.go index de61fe7..4b169bf 100644 --- a/command.go +++ b/command.go @@ -4,9 +4,12 @@ import ( "errors" "fmt" "reflect" + "regexp" "slices" ) +var commandNameExpression = regexp.MustCompile("^[a-zA-Z_][a-zA-Z_0-9]*$") + func command(name string, impl any, subcmds ...Cmd) Cmd { return Cmd{ name: name, @@ -74,7 +77,7 @@ func validateParameter(visited map[reflect.Type]bool, t reflect.Type) error { return validateParameter(visited, t) case reflect.Interface: if t.NumMethod() > 0 { - return errors.New("'non-empty' interface parameter") + return errors.New("non-empty interface parameter") } return nil @@ -203,11 +206,19 @@ func validateShortForms(cmd Cmd, assignedShortForms map[string]string) error { return nil } -func validateCommandTree(cmd Cmd, conf Config, assignedShortForms map[string]string) error { +func validateCommandTree(cmd Cmd, conf Config, assignedShortForms map[string]string, root bool) error { if cmd.isHelp { return nil } + if cmd.version != "" { + return nil + } + + if !root && !commandNameExpression.MatchString(cmd.name) { + return fmt.Errorf("command name is not a valid symbol: '%s'", cmd.name) + } + if cmd.impl != nil { if err := validateImpl(cmd, conf); err != nil { return fmt.Errorf("%s: %w", cmd.name, err) @@ -236,7 +247,7 @@ func validateCommandTree(cmd Cmd, conf Config, assignedShortForms map[string]str } names[s.name] = true - if err := validateCommandTree(s, conf, assignedShortForms); err != nil { + if err := validateCommandTree(s, conf, assignedShortForms, false); err != nil { return fmt.Errorf("%s: %w", s.name, err) } @@ -275,7 +286,7 @@ func allShortForms(cmd Cmd) []string { func validateCommand(cmd Cmd, conf Config) error { assignedShortForms := make(map[string]string) - if err := validateCommandTree(cmd, conf, assignedShortForms); err != nil { + if err := validateCommandTree(cmd, conf, assignedShortForms, true); err != nil { return err } diff --git a/commandline.go b/commandline.go index fa334c0..c04d3cb 100644 --- a/commandline.go +++ b/commandline.go @@ -182,11 +182,6 @@ func selectCommand(cmd Cmd, args []string) (Cmd, []string, []string) { return defaultCommand(cmd), []string{cmd.name}, args } - if sc.isHelp { - cmd.helpRequested = true - return cmd, []string{cmd.name}, args[1:] - } - cmd, fullCommand, args := selectCommand(sc, args[1:]) fullCommand = append([]string{cmd.name}, fullCommand...) return cmd, fullCommand, args diff --git a/config.go b/config.go index dec6519..d415dcb 100644 --- a/config.go +++ b/config.go @@ -1,10 +1,12 @@ package wand import ( + "bytes" "errors" "fmt" "github.com/iancoleman/strcase" "io" + "io/ioutil" "os" ) @@ -60,8 +62,14 @@ func (f *file) Close() error { } func readConfigFile(cmd Cmd, conf Config) (config, error) { - f := conf.file(cmd) - defer f.Close() + var f io.ReadCloser + if conf.test == "" { + f = conf.file(cmd) + defer f.Close() + } else { + f = ioutil.NopCloser(bytes.NewBufferString(conf.test)) + } + doc, err := parse(f) if err != nil { if conf.optional && (errors.Is(err, os.ErrPermission) || errors.Is(err, os.ErrNotExist)) { @@ -165,7 +173,7 @@ func readMergeConfig(cmd Cmd, cl commandLine, conf Config) (config, error) { } func readConfig(cmd Cmd, cl commandLine, conf Config) (config, error) { - if conf.file != nil { + if conf.file != nil || conf.test != "" { return readConfigFile(cmd, conf) } diff --git a/doclets.go b/doclets.go new file mode 100644 index 0000000..42cce4a --- /dev/null +++ b/doclets.go @@ -0,0 +1,27 @@ +package wand + +const envDocs = `Every command line option's value can also be provided as an environment variable. Environment variable +names need to use snake casing like myapp_foo_bar_baz or MYAPP_FOO_BAR_BAZ, or other casing that doesn't include the '-' dash +character, and they need to be prefixed with the name of the application, as in the base name of the command. When both the +environment variable and the command line option is defined, the command line option overrides the environment variable. +Multiple values for the same environment variable can be defined by concatenating the values with the ':' separator +character. When overriding multiple values with command line options, all the environment values of the same field are +dropped.` + +const configOptionDocs = `the config option allows to define zero or more configuration files at arbitrary path` + +const configDocs = `Every command line option's value can also be provided as an entry in a configuration file. Configuration +file entries can use keys with different casings, e.g. snake case foo_bar_baz, or kebab case foo-bar-baz. The keys of the +entries can use a limited set of characters: [a-zA-Z0-9_-], and the first character needs to be one of [a-zA-Z_]. Entry +values can consist of any characters, except for newline, control characters, " (quote) and \ (backslash), or the values can +be quoted, in which case they can consist of any characters, spanning multiple lines, and only the " (quote) and \ (backslash) +characters need to be escaped by the \ (backslash) character. Configuration files allow multiple entries with the same key, +when if the associated command line option also allows multiple instances (marked with [*]). When an entry is defined +multiple configuration files, the effective value is overridden in the order of the definition of the possible config files +(see the listing order below). To discard values defined in the overridden config files without defining new ones, we can +set entries with only the key, omitting the = key/value separator. Entries in the config files are overridden by the +environment variables, when defined, and by the command line options when defined. Config files marked as optional don't +need to be present in the file system, but if they exist, then they must contain valid configuration syntax which is wand's +flavor of .ini files (https://code.squareroundforest.org/arpio/ini.treerack).` + +const versionDocs = `Print the version of the current binary release.` diff --git a/exec.go b/exec.go index a60ab9e..85b2ae2 100644 --- a/exec.go +++ b/exec.go @@ -3,7 +3,6 @@ package wand import ( "errors" "fmt" - "github.com/iancoleman/strcase" "io" "os" "path/filepath" @@ -13,9 +12,10 @@ import ( func exec(stdin io.Reader, stdout, stderr io.Writer, exit func(int), cmd Cmd, conf Config, env, args []string) { cmd = insertHelp(cmd) _, cmd.name = filepath.Split(args[0]) - cmd.name = strcase.ToKebab(cmd.name) if err := validateCommand(cmd, conf); err != nil { - panic(err) + fmt.Fprintf(stderr, "program error: %v\n", err) + exit(1) + return } if os.Getenv("wandgenerate") == "man" { @@ -39,6 +39,39 @@ func exec(stdin io.Reader, stdout, stderr io.Writer, exit func(int), cmd Cmd, co e := readEnv(cmd.name, env) cmd, fullCmd, args := selectCommand(cmd, args[1:]) + if cmd.isHelp { + if err := showHelp(stdout, cmd, conf, fullCmd); err != nil { + fmt.Fprintln(stderr, err) + exit(1) + } + + return + } + + if cmd.version != "" { + if err := showVersion(stdout, cmd); err != nil { + fmt.Fprintln(stderr, err) + exit(1) + } + + return + } + + var bo []string + if cmd.impl != nil { + bo = boolOptions(cmd) + } + + cl := readArgs(bo, args) + if hasHelpOption(cmd, cl.options) { + if err := showHelp(stdout, cmd, conf, fullCmd); err != nil { + fmt.Fprintln(stderr, err) + exit(1) + } + + return + } + if cmd.impl == nil { fmt.Fprintln(stderr, errors.New("subcommand not specified")) suggestHelp(stderr, cmd, fullCmd) @@ -46,26 +79,6 @@ func exec(stdin io.Reader, stdout, stderr io.Writer, exit func(int), cmd Cmd, co return } - if cmd.helpRequested { - if err := showHelp(stdout, cmd, fullCmd, conf); err != nil { - fmt.Fprintln(stderr, err) - exit(1) - } - - return - } - - bo := boolOptions(cmd) - cl := readArgs(bo, args) - if hasHelpOption(cmd, cl.options) { - if err := showHelp(stdout, cmd, fullCmd, conf); err != nil { - fmt.Fprintln(stderr, err) - exit(1) - } - - return - } - c, err := readConfig(cmd, cl, conf) if err != nil { fmt.Fprintf(stderr, "configuration error: %v", err) diff --git a/exec_test.go b/exec_test.go index 70236c5..1ffe2bb 100644 --- a/exec_test.go +++ b/exec_test.go @@ -1,23 +1,37 @@ package wand -/* import ( "bytes" "fmt" + "io" "strings" "testing" ) -func testExec(impl any, env, commandLine, err string, expect ...string) func(*testing.T) { +type testCase struct { + impl any + stdin string + conf string + env string + command string +} + +func testExec(test testCase, err string, expect ...string) func(*testing.T) { return func(t *testing.T) { var exitCode int exit := func(code int) { exitCode = code } + + var stdinr io.Reader + if test.stdin != "" { + stdinr = bytes.NewBuffer([]byte(test.stdin)) + } + stdout := bytes.NewBuffer(nil) stderr := bytes.NewBuffer(nil) - cmd := wrap(impl) - e := strings.Split(env, ";") - a := strings.Split(commandLine, " ") - exec(stdout, stderr, exit, cmd, e, a) + cmd := wrap(test.impl) + e := strings.Split(test.env, ";") + a := strings.Split(test.command, " ") + exec(stdinr, stdout, stderr, exit, cmd, Config{test: test.conf}, e, a) if exitCode != 0 && err == "" { t.Fatal("non-zero exit code:", stderr.String()) } @@ -39,9 +53,13 @@ func testExec(impl any, env, commandLine, err string, expect ...string) func(*te expstr = append(expstr, fmt.Sprint(e)) } - if stdout.String() != strings.Join(expstr, "\n")+"\n" { + output := stdout.String() + if output[len(output) - 1] != '\n' { + output = output + "\n" + } + + if output != strings.Join(expstr, "\n")+"\n" { t.Fatal("unexpected output:", stdout.String()) } } } -*/ diff --git a/format.go b/format.go new file mode 100644 index 0000000..f246716 --- /dev/null +++ b/format.go @@ -0,0 +1,201 @@ +package wand + +import ( + "fmt" + "io" + "sort" + "strings" +) + +func printer(out io.Writer) (printf func(f string, args ...any), println func(args ...any), finish func() error) { + var err error + printf = func(f string, args ...any) { + if err != nil { + return + } + + _, err = fmt.Fprintf(out, f, args...) + } + + println = func(args ...any) { + if err != nil { + return + } + + _, err = fmt.Fprintln(out, args...) + } + + finish = func() error { + return err + } + + return +} + +func paragraphs(s string) string { + var ( + paragraph []string + paragraphs [][]string + ) + + l := strings.Split(s, "\n") + for i := range l { + l[i] = strings.TrimSpace(l[i]) + if l[i] == "" { + if len(paragraph) > 0 { + paragraphs, paragraph = append(paragraphs, paragraph), nil + } + + continue + } + + paragraph = append(paragraph, l[i]) + } + + if len(paragraph) > 0 { + paragraphs = append(paragraphs, paragraph) + } + + var cparagraphs []string + for _, p := range paragraphs { + cparagraphs = append(cparagraphs, strings.Join(p, " ")) + } + + return strings.Join(cparagraphs, "\n\n") +} + +func lines(s string) string { + p := paragraphs(s) + pp := strings.Split(p, "\n\n") + return strings.Join(pp, "\n") +} + +func escapeTeletype(s string) string { + r := []rune(s) + for i := range r { + if r[i] >= 0x00 && r[i] <= 0x1f && r[i] != '\n' && r[i] != '\t' { + r[i] = 0xb7 + } + + if r[i] >= 0x7f && r[i] <= 0x9f { + r[i] = 0xb7 + } + } + + return string(r) +} + +func manParagraphs(s string) string { + p := paragraphs(s) + pp := strings.Split(p, "\n\n") + for i := range pp { + pp[i] = fmt.Sprintf(".PP\n%s", pp[i]) + } + + return strings.Join(pp, "\n") +} + +func manLines(s string) string { + l := lines(s) + ll := strings.Split(l, "\n") + for i := range ll { + ll[i] = fmt.Sprintf(".br\n%s", ll[i]) + } + + return strings.Join(ll, "\n") +} + +func escapeRoff(s string) string { + var ( + rr []rune + lastNewline bool + ) + + r := []rune(s) + for _, ri := range r { + switch ri { + case '\\', '-', '"': + rr = append(rr, '\\', ri) + case '.', '\'': + if lastNewline { + rr = append(rr, '\\') + } + + rr = append(rr, ri) + case 0x2013: + rr = append(rr, []rune("\\(en")...) + case 0x2014: + rr = append(rr, []rune("\\(em")...) + case 0x201c: + rr = append(rr, []rune("\\(lq")...) + case 0x201d: + rr = append(rr, []rune("\\(rq")...) + case 0x2018: + rr = append(rr, []rune("\\(oq")...) + case 0x2019: + rr = append(rr, []rune("\\(cq")...) + default: + rr = append(rr, ri) + } + + lastNewline = ri == '\n' + } + + return string(rr) +} + +func escapeMD(s string) string { + var ( + rr []rune + lastDigit bool + ) + + r := []rune(s) + for _, ri := range r { + switch ri { + case '*', '_', '#', '-', '+', '[', ']', '`', '<', '>', '|', '\\': + rr = append(rr, '\\', ri) + case '.': + if lastDigit { + rr = append(rr, '\\') + } + + rr = append(rr, ri) + default: + rr = append(rr, ri) + lastDigit = ri >= 0 && ri <= 9 + } + } + + return string(rr) +} + +func prepareOptions(o []docOption) (names []string, descriptions map[string]string) { + for _, oi := range o { + ons := []string{fmt.Sprintf("--%s", oi.name)} + for _, sn := range oi.shortNames { + ons = append(ons, fmt.Sprintf("-%s", sn)) + } + + n := strings.Join(ons, ", ") + if oi.isBool { + n = fmt.Sprintf("%s [b]", n) + } else { + n = fmt.Sprintf("%s %s", n, oi.typ) + } + + if oi.acceptsMultiple { + n = fmt.Sprintf("%s [*]", n) + } + + names = append(names, n) + if descriptions == nil { + descriptions = make(map[string]string) + } + + descriptions[n] = oi.description + } + + sort.Strings(names) + return +} diff --git a/formathelp.go b/formathelp.go index ed0fb71..2c997d7 100644 --- a/formathelp.go +++ b/formathelp.go @@ -8,25 +8,9 @@ import ( "strings" ) -func formatHelp(w io.Writer, doc doc) error { - var err error - println := func(a ...any) { - if err != nil { - return - } - - _, err = fmt.Fprintln(w, a...) - } - - printf := func(f string, a ...any) { - if err != nil { - return - } - - _, err = fmt.Fprintf(w, f, a...) - } - - printf(doc.fullCommand) +func formatHelp(out io.Writer, doc doc) error { + printf, println, finish := printer(out) + printf(escapeTeletype(doc.fullCommand)) println() if doc.hasImplementation || doc.synopsis.hasSubcommands { println() @@ -36,23 +20,30 @@ func formatHelp(w io.Writer, doc doc) error { if doc.hasImplementation { println() - printf(doc.synopsis.command) + printf(escapeTeletype(doc.synopsis.command)) if doc.synopsis.hasOptions { - printf(" [options ...]") + printf(" [options...]") } - for _, n := range doc.synopsis.arguments.names { - printf(" %s", n) + for i := range doc.synopsis.arguments.names { + printf( + " [%s %s]", + doc.synopsis.arguments.names[i], + doc.synopsis.arguments.types[i], + ) } if doc.synopsis.arguments.variadic { printf("...") - if doc.synopsis.arguments.minPositional > 0 { - printf(" min %d arguments", doc.synopsis.arguments.minPositional) - } - - if doc.synopsis.arguments.maxPositional > 0 { - printf(" max %d arguments", doc.synopsis.arguments.maxPositional) + min := doc.synopsis.arguments.minPositional + max := doc.synopsis.arguments.maxPositional + switch { + case min > 0 && max > 0: + printf("\nmin %d and max %d total positional arguments", min, max) + case min > 0: + printf("\nmin %d total positional arguments", min) + case max > 0: + printf("\nmax %d total positional arguments", max) } } @@ -60,56 +51,39 @@ func formatHelp(w io.Writer, doc doc) error { } if doc.synopsis.hasSubcommands { - if !doc.hasImplementation { - println() - } - - printf("%s [options or args...]", doc.synopsis.command) + println() + printf("%s [options or args...]", escapeTeletype(doc.synopsis.command)) println() println() - printf("(For the details about the available subcommands, see the according section below.)") + printf("(For the details about the available subcommands, see the related section below.)") println() } - if len(doc.description) > 0 { + if doc.description != "" { println() - printf(paragraphs(doc.description)) + printf(escapeTeletype(paragraphs(doc.description))) println() } if len(doc.options) > 0 { println() printf("Options") - println() - println() - printf("[*]: accepts multiple instances of the same option") - println() - printf("[b]: booelan flag, true or false, or no argument means true") - println() - println() - - var names []string - od := make(map[string]string) - for _, o := range doc.options { - ons := []string{fmt.Sprintf("--%s", o.name)} - for _, sn := range o.shortNames { - ons = append(ons, fmt.Sprintf("-%s", sn)) + if doc.hasBoolOptions || doc.hasListOptions { + println() + if doc.hasBoolOptions { + println() + printf("[b]: booelan flag, true or false, or no argument means true") } - n := strings.Join(ons, ", ") - if o.acceptsMultiple { - n = fmt.Sprintf("%s [*]", n) + if doc.hasListOptions { + println() + printf("[*]: accepts multiple instances of the same option") } - - if o.isBool { - n = fmt.Sprintf("%s [b]", n) - } - - names = append(names, n) - od[n] = o.description } - sort.Strings(names) + println() + println() + names, od := prepareOptions(doc.options) var max int for _, n := range names { @@ -120,13 +94,13 @@ func formatHelp(w io.Writer, doc doc) error { for i := range names { pad := strings.Join(make([]string, max-len(names[i])+1), " ") - names[i] = fmt.Sprintf("%s%s", names[i], pad) + names[i] = fmt.Sprintf("%s:%s", names[i], pad) } for _, n := range names { printf(n) if od[n] != "" { - printf(": %s", paragraphs(od[n])) + printf(" %s", escapeTeletype(lines(od[n]))) } println() @@ -153,9 +127,9 @@ func formatHelp(w io.Writer, doc doc) error { } if sc.hasHelpSubcommand { - d = fmt.Sprintf("%s - For help, see: %s %s help", d, doc.name, sc.name) + d = fmt.Sprintf("%s - For help, see: %s %s help", d, escapeTeletype(doc.name), sc.name) } else if sc.hasHelpOption { - d = fmt.Sprintf("%s - For help, see: %s %s --help", d, doc.name, sc.name) + d = fmt.Sprintf("%s - For help, see: %s %s --help", d, escapeTeletype(doc.name), sc.name) } cd[name] = d @@ -178,22 +152,24 @@ func formatHelp(w io.Writer, doc doc) error { for _, n := range names { printf(n) if cd[n] != "" { - printf(": %s", paragraphs(cd[n])) + printf(": %s", escapeTeletype(paragraphs(cd[n]))) } println() } } - if len(doc.options) > 0 { - printf(paragraphs(envDocs)) + if len(doc.options) > 0 && commandNameExpression.MatchString(doc.appName) { + println("Environment Variables") + println() + printf(escapeTeletype(paragraphs(envDocs))) println() println() o := doc.options[0] printf("Example environment variable:") println() println() - printf(strcase.ToSnake(o.name)) + printf(strcase.ToSnake(fmt.Sprintf("%s-%s", doc.appName, o.name))) printf("=") if o.isBool { printf("true") @@ -205,7 +181,9 @@ func formatHelp(w io.Writer, doc doc) error { } if len(doc.options) > 0 && len(doc.configFiles) > 0 { - printf(paragraphs(configDocs)) + println("Configuration Files") + println() + printf(escapeTeletype(paragraphs(configDocs))) println() println() printf("Config files:") @@ -236,6 +214,7 @@ func formatHelp(w io.Writer, doc doc) error { println() printf("# default for --") printf(o.name) + printf(":") println() printf(strcase.ToSnake(o.name)) printf(" = ") @@ -246,7 +225,15 @@ func formatHelp(w io.Writer, doc doc) error { } println() + println() + printf("Example for discarding an inherited entry:") + println() + println() + printf("# discarding an inherited entry:") + println() + printf(strcase.ToSnake(o.name)) + println() } - return err + return finish() } diff --git a/formatman.go b/formatman.go index f068931..b90d901 100644 --- a/formatman.go +++ b/formatman.go @@ -1,11 +1,204 @@ package wand -import "io" +import ( + "fmt" + "github.com/iancoleman/strcase" + "io" + "strings" + "time" +) + +func formatManCommand(printf func(string, ...any), println func(...any), doc doc) { + println(".SH Synopsis") + printf(".B %s", escapeRoff(doc.synopsis.command)) + if doc.synopsis.hasOptions { + printf(" [options...]") + } + + for i := range doc.synopsis.arguments.names { + printf( + " [%s %s]", + doc.synopsis.arguments.names[i], + doc.synopsis.arguments.types[i], + ) + } + + min := doc.synopsis.arguments.minPositional + max := doc.synopsis.arguments.maxPositional + if doc.synopsis.arguments.variadic { + println("...") + if min > 0 || max > 0 { + println(".PP") + } + + switch { + case min > 0 && max > 0: + printf("min %d and max %d total positional arguments\n", min, max) + case min > 0: + printf("min %d total positional arguments\n", min) + case max > 0: + printf("max %d total positional arguments\n", max) + } + } + + if doc.synopsis.hasSubcommands { + if min > 0 || max > 0 { + println(".PP") + } + + for i, sc := range doc.subcommands { + if i > 0 { + println(".br") + } + + printf("%s %s\n", escapeRoff(doc.name), sc.name) + } + } + + if doc.description != "" { + println(".SH Description") + println(manParagraphs(escapeRoff(doc.description))) + } + + if len(doc.options) > 0 { + println(".SH Options") + if doc.hasBoolOptions || doc.hasListOptions { + println(".PP") + } + + if doc.hasBoolOptions { + println(".B [b]:") + println("booelan flag, true or false, or no argument means true") + } + + if doc.hasListOptions { + if doc.hasBoolOptions { + println(".br") + } + + println(".B [*]:") + println("accepts multiple instances of the same option") + } + + names, descriptions := prepareOptions(doc.options) + for _, n := range names { + println(".TP") + printf(".B %s\n", escapeRoff(n)) + if descriptions[n] != "" { + println(manLines(escapeRoff(descriptions[n]))) + } + } + } + + if len(doc.options) > 0 && commandNameExpression.MatchString(doc.appName) { + println(".SH Environment Variables") + println(manParagraphs(escapeRoff(envDocs))) + println(".PP Example environment variable:") + o := doc.options[0] + println(".TP") + printf(strcase.ToSnake(fmt.Sprintf("%s-%s", doc.appName, o.name))) + printf("=") + if o.isBool { + printf("true") + } else { + printf("42") + } + + println() + } + + if len(doc.options) > 0 && len(doc.configFiles) > 0 { + println(".SH Configuration Files") + println(manParagraphs(escapeRoff(configDocs))) + println(".PP Config files:") + for i, cf := range doc.configFiles { + if i > 0 { + println(".br") + } + + if cf.fromOption { + println(escapeRoff("zero or more configuration files defined by the --config option")) + continue + } + + if cf.fn != "" { + printf(escapeRoff(cf.fn)) + if cf.optional { + printf(" (optional)") + } + + println() + continue + } + } + + println(".PP Example configuration entry:") + println(".PP") + o := doc.options[0] + printf(escapeRoff(fmt.Sprintf("# default for --%s:\n", o.name))) + println(".br") + printf(escapeRoff(strcase.ToSnake(o.name))) + printf(" = ") + if o.isBool { + printf("true") + } else { + printf("42") + } + + println() + println(".PP Example for discarding an inherited entry:") + println(".PP") + println("# discarding an inherited entry:") + println(".br") + println(escapeRoff(strcase.ToSnake(o.name))) + } +} + +func formatManMultiCommand(out io.Writer, doc doc) error { + printf, println, finish := printer(out) + printf(".TH %s 1 %s \"%s\"\n", escapeRoff(doc.appName), escapeRoff(doc.date.Format(time.DateOnly)), escapeRoff(doc.appName)) + printf(".SH Name\n%s\n", escapeRoff(doc.appName)) + println(".SH Provides several commands:") + println(".PP") + allCommands := allCommands(doc) + for i, c := range allCommands { + if i > 0 { + println(".br") + } + + println(escapeRoff(c.fullCommand)) + } + + for _, c := range allCommands { + printf(".SH %s\n", escapeRoff(strings.ToUpper(c.fullCommand))) + formatManCommand(printf, println, c) + } + + return finish() +} + +func formatManSingleCommand(out io.Writer, doc doc) error { + printf, println, finish := printer(out) + printf(".TH %s 1 %s \"%s\"\n", escapeRoff(doc.appName), escapeRoff(doc.date.Format(time.DateOnly)), escapeRoff(doc.appName)) + printf(".SH Name\n%s\n", escapeRoff(doc.appName)) + formatManCommand(printf, println, doc) + return finish() +} func formatMan(out io.Writer, doc doc) error { - // if no subcommands, then similar to help - // otherwise: - // title - // all commands - return nil + var hasSubcommands bool + for _, sc := range doc.subcommands { + if !sc.isHelp && !sc.isVersion { + continue + } + + hasSubcommands = true + break + } + + if hasSubcommands { + return formatManMultiCommand(out, doc) + } + + return formatManSingleCommand(out, doc) } diff --git a/formatmarkdown.go b/formatmarkdown.go index 7ec5bcc..d82fafa 100644 --- a/formatmarkdown.go +++ b/formatmarkdown.go @@ -1,11 +1,201 @@ package wand -import "io" +import ( + "fmt" + "github.com/iancoleman/strcase" + "io" + "strings" +) + +func header(level int) string { + s := make([]string, level+2) + return strings.Join(s, "#") +} + +func formatMarkdownCommand(printf func(string, ...any), println func(...any), doc doc, level int) { + printf("%s Synopsis\n\n", header(level)) + println("```") + printf(doc.synopsis.command) + if doc.synopsis.hasOptions { + printf(" [options...]") + } + + for i := range doc.synopsis.arguments.names { + printf( + " [%s %s]", + doc.synopsis.arguments.names[i], + doc.synopsis.arguments.types[i], + ) + } + + if doc.synopsis.arguments.variadic { + printf("...") + } + + println() + println("```") + + min := doc.synopsis.arguments.minPositional + max := doc.synopsis.arguments.maxPositional + if doc.synopsis.arguments.variadic { + if min > 0 || max > 0 { + println() + } + + switch { + case min > 0 && max > 0: + printf("min %d and max %d total positional arguments\n", min, max) + case min > 0: + printf("min %d total positional arguments\n", min) + case max > 0: + printf("max %d total positional arguments\n", max) + } + } + + if doc.synopsis.hasSubcommands { + println() + println("```") + for _, sc := range doc.subcommands { + printf("%s %s\n", escapeMD(doc.name), sc.name) + } + + println("```") + } + + if doc.description != "" { + printf("\n%s Description\n\n", header(level)) + println(escapeMD(paragraphs(doc.description))) + } + + if len(doc.options) > 0 { + printf("\n%s Options\n\n", header(level)) + if doc.hasBoolOptions { + printf("- [b]: booelan flag, true or false, or no argument means true\n") + } + + if doc.hasListOptions { + printf("- [*]: accepts multiple instances of the same option\n") + } + + if doc.hasBoolOptions || doc.hasListOptions { + println() + } + + names, descriptions := prepareOptions(doc.options) + for _, n := range names { + printf("- **%s**: %s\n", escapeMD(n), escapeMD(lines(descriptions[n]))) + } + } + + if len(doc.options) > 0 && commandNameExpression.MatchString(doc.appName) { + printf("\n.%s Environment Variables\n\n", header(level)) + println(escapeMD(paragraphs(envDocs))) + println() + println("Example environment variable:") + println() + o := doc.options[0] + println("```") + printf(strcase.ToSnake(fmt.Sprintf("%s-%s", doc.appName, o.name))) + printf("=") + if o.isBool { + printf("true") + } else { + printf("42") + } + + println() + println("```") + } + + if len(doc.options) > 0 && len(doc.configFiles) > 0 { + printf("\n.Configuration Files\n\n") + println(escapeMD(paragraphs(configDocs))) + println() + println("Config files:") + println() + for _, cf := range doc.configFiles { + if cf.fromOption { + println("- zero or more configuration files defined by the --config option\n") + continue + } + + if cf.fn != "" { + printf("- %s", cf.fn) + if cf.optional { + printf(" (optional)") + } + + println() + continue + } + } + + println() + println("Example configuration entry:") + println() + o := doc.options[0] + println("```") + printf("# default for --%s:\n", o.name) + printf(strcase.ToSnake(o.name)) + printf(" = ") + if o.isBool { + printf("true") + } else { + printf("42") + } + + println() + println("```") + println() + println("Example for discarding an inherited entry:") + println() + println("```") + println("# discarding an inherited entry:") + println(strcase.ToSnake(o.name)) + println("```") + } +} + +func formatMarkdownMultiCommand(out io.Writer, doc doc, level int) error { + printf, println, finish := printer(out) + printf("%s %s\n\n", header(level), escapeMD(doc.appName)) + println("Provides several commands:") + println() + allCommands := allCommands(doc) + for _, c := range allCommands { + printf("- %s\n", escapeMD(c.fullCommand)) + } + + println() + for _, c := range allCommands { + printf("%s %s\n\n", header(level+1), escapeMD(c.fullCommand)) + formatMarkdownCommand(printf, println, c, level+2) + } + + return finish() +} + +func formatMarkdownSingleCommand(out io.Writer, doc doc, level int) error { + printf, println, finish := printer(out) + printf("%s %s\n\n", header(level), doc.appName) + formatMarkdownCommand(printf, println, doc, level+1) + return finish() +} func formatMarkdown(out io.Writer, doc doc, level int) error { - // if no subcommands, then similar to help - // otherwise: - // title - // all commands - return nil + var hasSubcommands bool + for _, sc := range doc.subcommands { + if !sc.isHelp && !sc.isVersion { + continue + } + + hasSubcommands = true + break + } + + if hasSubcommands { + return formatMarkdownMultiCommand(out, doc, level) + } + + return formatMarkdownSingleCommand(out, doc, level) } diff --git a/help.go b/help.go index b5dab1b..2afac35 100644 --- a/help.go +++ b/help.go @@ -5,41 +5,16 @@ import ( "fmt" "io" "reflect" + "sort" "strings" + "time" ) -const defaultWrap = 112 - -const envDocs = `Environment Variables - -Every command line option's value can also be provided as an environment variable. Environment variable names need to use -snake casing like foo_bar_baz or FOO_BAR_BAZ, or other casing that doesn't include the '-' dash character. When both the -environment variable and the command line option is defined, the command line option overrides the environment variable. -Multiple values for the same environment variable can be defined by concatenating the values with the ':' separator -character. When overriding multiple values with command line options, all the environment values of the same field are -dropped.` - -const configOptionDocs = `the config option allows to define zero or more configuration files at arbitrary path` - -const configDocs = `Configuration Files - -Every command line option's value can also be provided as an entry in a configuration file. Configuration file entries -can use keys with different casings, e.g. snake case foo_bar_baz, or kebab case foo-bar-baz. The keys of the entries -can use a limited set of characters: [a-zA-Z0-9_-], and the first character needs to be one of [a-zA-Z_]. Entry values can -consist of any characters, except for newline, control characters, " (quote) and \ (backslash), or the values can be quoted, -in which case they can consist of any characters, spanning multiple lines, and only the " (quote) and \ (backslash) -characters need to be escaped by the \ (backslash) character. Configuration files allow multiple entries with the same key, -when if the associated command line option also allows multiple instances (marked with [*]). When an entry is defined -multiple configuration files, the effective value is overridden in the order of the definition of the possible config files -(see the listing order below). Entries in the config files are overridden by the environment variables, when defined, and by -the command line options when defined. Config files marked as optional don't need to exist in the file system, but if they -exist, then they must contain valid configuration syntax which is wand's flavor of .ini files -(https://code.squareroundforest.org/arpio/ini.treerack).` - type ( argumentSet struct { count int names []string + types []string variadic bool usesStdin bool usesStdout bool @@ -56,6 +31,7 @@ type ( docOption struct { name string + typ string description string shortNames []string isBool bool @@ -70,19 +46,24 @@ type ( doc struct { name string + appName string fullCommand string synopsis synopsis description string hasImplementation bool isHelp bool + isVersion bool isDefault bool hasHelpSubcommand bool hasHelpOption bool hasConfigFromOption bool options []docOption + hasBoolOptions bool + hasListOptions bool arguments argumentSet subcommands []doc configFiles []docConfig + date time.Time } ) @@ -102,7 +83,7 @@ func insertHelp(cmd Cmd) Cmd { } } - if !hasHelpCmd { + if !hasHelpCmd && cmd.version == "" { cmd.subcommands = append(cmd.subcommands, help()) } @@ -120,6 +101,10 @@ func hasHelpSubcommand(cmd Cmd) bool { } func hasCustomHelpOption(cmd Cmd) bool { + if cmd.impl == nil { + return false + } + mf := mapFields(cmd.impl) _, has := mf["help"] return has @@ -149,13 +134,38 @@ func hasOptions(cmd Cmd) bool { return len(fields(s...)) > 0 } -func functionParams(v reflect.Value, skip []int) []string { - names := docreflect.FunctionParams(v) - for _, i := range skip { - names = append(names[:i], names[i+1:]...) +func allCommands(cmd doc) []doc { + commands := []doc{cmd} + for _, sc := range cmd.subcommands { + commands = append(commands, allCommands(sc)...) } - return names + sort.Slice(commands, func(i, j int) bool { + return commands[i].fullCommand < commands[j].fullCommand + }) + + return commands +} + +func functionParams(v reflect.Value, skip []int) ([]string, []string) { + names := docreflect.FunctionParams(v) + + var types []reflect.Kind + for i := 0; i < v.Type().NumIn(); i++ { + types = append(types, v.Type().In(i).Kind()) + } + + for _, i := range skip { + names = append(names[:i], names[i+1:]...) + types = append(types[:i], types[i+1:]...) + } + + var stypes []string + for _, t := range types { + stypes = append(stypes, strings.ToLower(fmt.Sprint(t))) + } + + return names, stypes } func constructArguments(cmd Cmd) argumentSet { @@ -163,12 +173,12 @@ func constructArguments(cmd Cmd) argumentSet { return argumentSet{} } - v := reflect.ValueOf(cmd.impl) - t := unpack(v.Type()) + v := unpack(reflect.ValueOf(cmd.impl)) + t := v.Type() p := positionalParameters(t) ior, iow := ioParameters(p) count := len(p) - len(ior) - len(iow) - names := functionParams(v, append(ior, iow...)) + names, types := functionParams(v, append(ior, iow...)) if len(names) < count { names = nil for i := 0; i < count; i++ { @@ -179,6 +189,7 @@ func constructArguments(cmd Cmd) argumentSet { return argumentSet{ count: count, names: names, + types: types, variadic: t.IsVariadic(), usesStdin: len(ior) > 0, usesStdout: len(iow) > 0, @@ -197,6 +208,10 @@ func constructSynopsis(cmd Cmd, fullCommand []string) synopsis { } func constructDescription(cmd Cmd) string { + if cmd.version != "" { + return versionDocs + } + if cmd.impl == nil { return "" } @@ -230,6 +245,7 @@ func constructOptions(cmd Cmd, hasConfigFromOption bool) []docOption { for name, fi := range f { opt := docOption{ name: name, + typ: strings.ToLower(fmt.Sprint(fi[0].typ.Kind())), description: d[name], shortNames: sf[name], isBool: fi[0].typ.Kind() == reflect.Bool, @@ -275,70 +291,64 @@ func constructConfigDocs(cmd Cmd, conf Config) []docConfig { return docs } -func constructDoc(cmd Cmd, conf Config, fullCommand []string, hasConfigFromOption bool) doc { +func constructDoc(cmd Cmd, conf Config, fullCommand []string) doc { + hasConfigFromOption := hasConfigFromOption(conf) + var subcommands []doc for _, sc := range cmd.subcommands { - subcommands = append(subcommands, constructDoc(sc, conf, append(fullCommand, sc.name), hasConfigFromOption)) + subcommands = append(subcommands, constructDoc(sc, conf, append(fullCommand, sc.name))) + } + + var hasBoolOptions, hasListOptions bool + options := constructOptions(cmd, hasConfigFromOption) + for _, o := range options { + if o.isBool { + hasBoolOptions = true + } + + if o.acceptsMultiple { + hasListOptions = true + } } return doc{ - name: fullCommand[len(fullCommand)-1], + name: cmd.name, + appName: fullCommand[0], fullCommand: strings.Join(fullCommand, " "), synopsis: constructSynopsis(cmd, fullCommand), description: constructDescription(cmd), hasImplementation: cmd.impl != nil, isDefault: cmd.isDefault, isHelp: cmd.isHelp, + isVersion: cmd.version != "", hasHelpSubcommand: hasHelpSubcommand(cmd), hasHelpOption: hasCustomHelpOption(cmd), - options: constructOptions(cmd, hasConfigFromOption), + options: options, + hasBoolOptions: hasBoolOptions, + hasListOptions: hasListOptions, arguments: constructArguments(cmd), subcommands: subcommands, configFiles: constructConfigDocs(cmd, conf), + date: time.Now(), } } -func paragraphs(s string) string { - var ( - paragraph []string - paragraphs [][]string - ) - - l := strings.Split(s, "\n") - for i := range l { - l[i] = strings.TrimSpace(l[i]) - if l[i] == "" { - if len(paragraph) > 0 { - paragraphs, paragraph = append(paragraphs, paragraph), nil - } - - continue - } - - paragraph = append(paragraph, l[i]) - } - - paragraphs = append(paragraphs, paragraph) - - var cparagraphs []string - for _, p := range paragraphs { - cparagraphs = append(cparagraphs, strings.Join(p, " ")) - } - - return strings.Join(cparagraphs, "\n\n") -} - -func showHelp(out io.Writer, cmd Cmd, fullCommand []string, conf Config) error { - doc := constructDoc(cmd, conf, fullCommand, hasConfigFromOption(conf)) +func showHelp(out io.Writer, cmd Cmd, conf Config, fullCommand []string) error { + doc := constructDoc(cmd, conf, fullCommand) return formatHelp(out, doc) } func generateMan(out io.Writer, cmd Cmd, conf Config) error { - doc := constructDoc(cmd, conf, []string{cmd.name}, hasConfigFromOption(conf)) + doc := constructDoc(cmd, conf, []string{cmd.name}) return formatMan(out, doc) } func generateMarkdown(out io.Writer, cmd Cmd, conf Config, level int) error { - doc := constructDoc(cmd, conf, []string{cmd.name}, hasConfigFromOption(conf)) + doc := constructDoc(cmd, conf, []string{cmd.name}) return formatMarkdown(out, doc, level) } + +func showVersion(out io.Writer, cmd Cmd) error { + _, err := fmt.Fprintln(out, cmd.version) + return err +} diff --git a/input.go b/input.go index 95fe5ac..d621da2 100644 --- a/input.go +++ b/input.go @@ -149,6 +149,10 @@ func validatePositionalArgs(cmd Cmd, a []string) error { } for i, ai := range a { + if slices.Contains(ior, i) || slices.Contains(iow, i) { + continue + } + var pi reflect.Type if i >= length { pi = p[length-1] @@ -156,6 +160,10 @@ func validatePositionalArgs(cmd Cmd, a []string) error { pi = p[i] } + if pi.Kind() == reflect.Interface { + continue + } + if !canScan(pi, ai) { return fmt.Errorf( "cannot apply positional argument at index %d, expecting %v", diff --git a/notes.txt b/notes.txt index e69de29..870483d 100644 --- a/notes.txt +++ b/notes.txt @@ -0,0 +1,21 @@ +fix go.mod file path in exec +test starting from the most referenced file to the least referenced one +run only the related test when testing a file + +reflect +command +commandline +config +doclets +format +formathelp +formatman +formatmarkdown +help +env +input +output +apply +exec +wand +tools/tools diff --git a/reflect.go b/reflect.go index 023e704..0fb8103 100644 --- a/reflect.go +++ b/reflect.go @@ -80,7 +80,7 @@ func parseInt(s string, byteSize int) (int64, error) { case strings.HasPrefix(s, "0"): return strconv.ParseInt(s[1:], 8, bitSize) default: - return strconv.ParseInt(s[2:], 2, byteSize*8) + return strconv.ParseInt(s, 10, bitSize) } } @@ -94,7 +94,7 @@ func parseUint(s string, byteSize int) (uint64, error) { case strings.HasPrefix(s, "0"): return strconv.ParseUint(s[1:], 8, bitSize) default: - return strconv.ParseUint(s[2:], 2, bitSize) + return strconv.ParseUint(s, 10, bitSize) } } diff --git a/reflect_test.go b/reflect_test.go new file mode 100644 index 0000000..1307262 --- /dev/null +++ b/reflect_test.go @@ -0,0 +1,84 @@ +package wand + +import ( + "testing" + "io" + "bytes" +) + +func TestReflect(t *testing.T) { + t.Run("pack and unpack", func(t *testing.T) { + f := func(a int) int { return a } + t.Run("no need to pack", testExec(testCase{impl: f, command: "foo 42"}, "", "42")) + g := func(a *int) int { return *a } + t.Run("pointer", testExec(testCase{impl: g, command: "foo 42"}, "", "42")) + h := func(a []int) int { return a[0] } + t.Run("slice", testExec(testCase{impl: h, command: "foo 42"}, "", "42")) + i := func(a *[]*[]int) int { return (*((*a)[0]))[0] } + t.Run("pointer and slice", testExec(testCase{impl: i, command: "foo 42"}, "", "42")) + }) + + t.Run("io params", func(t *testing.T) { + f := func(in io.Reader) string { b, _ := io.ReadAll(in); return string(b) } + t.Run("in", testExec(testCase{impl: f, stdin: "foo", command: "bar"}, "", "foo")) + g := func(a string) io.Reader { return bytes.NewBufferString(a) } + t.Run("out", testExec(testCase{impl: g, command: "foo bar"}, "", "bar")) + h := func(out io.Writer, a string) { out.Write([]byte(a)) } + t.Run("stdout param", testExec(testCase{impl: h, command: "foo bar"}, "", "bar")) + }) + + t.Run("struct param", func(t *testing.T) { + f := func(s struct{Bar int}) int { return s.Bar } + t.Run("basic", testExec(testCase{impl: f, command: "foo --bar 42"}, "", "42")) + }) + + t.Run("basic types", func(t *testing.T) { + t.Run("signed int", func(t *testing.T) { + f := func(a int) int { return a } + t.Run("decimal", testExec(testCase{impl: f, command: "foo 42"}, "", "42")) + t.Run("hexa", testExec(testCase{impl: f, command: "foo 0x2a"}, "", "42")) + t.Run("octal", testExec(testCase{impl: f, command: "foo 052"}, "", "42")) + t.Run("binary", testExec(testCase{impl: f, command: "foo 0b101010"}, "", "42")) + t.Run("fail", testExec(testCase{impl: f, command: "foo bar"}, "expecting int", "")) + g := func(a int32) int32 { return a } + t.Run("sized", testExec(testCase{impl: g, command: "foo 42"}, "", "42")) + }) + + t.Run("unsigned int", func(t *testing.T) { + f := func(a uint) uint { return a } + t.Run("decimal", testExec(testCase{impl: f, command: "foo 42"}, "", "42")) + t.Run("hexa", testExec(testCase{impl: f, command: "foo 0x2a"}, "", "42")) + t.Run("octal", testExec(testCase{impl: f, command: "foo 052"}, "", "42")) + t.Run("binary", testExec(testCase{impl: f, command: "foo 0b101010"}, "", "42")) + t.Run("fail", testExec(testCase{impl: f, command: "foo bar"}, "expecting uint", "")) + g := func(a uint32) uint32 { return a } + t.Run("sized", testExec(testCase{impl: g, command: "foo 42"}, "", "42")) + }) + + t.Run("bool", func(t *testing.T) { + f := func(a bool) bool { return a } + t.Run("true", testExec(testCase{impl: f, command: "foo true"}, "", "true")) + t.Run("false", testExec(testCase{impl: f, command: "foo false"}, "", "false")) + t.Run("fail", testExec(testCase{impl: f, command: "foo yes"}, "expecting bool", "")) + }) + + t.Run("float", func(t *testing.T) { + f := func(a float64) float64 { return a } + t.Run("accept", testExec(testCase{impl: f, command: "foo 3.14"}, "", "3.14")) + t.Run("fail", testExec(testCase{impl: f, command: "foo bar"}, "expecting float", "")) + }) + + t.Run("string", func(t *testing.T) { + f := func(a string) string { return a } + t.Run("accept", testExec(testCase{impl: f, command: "foo bar"}, "", "bar")) + }) + + t.Run("interface", func(t *testing.T) { + f := func(a any) any { return a } + t.Run("any", testExec(testCase{impl: f, command: "foo bar"}, "", "bar")) + type i interface{Foo()} + g := func(a i) any { return a } + t.Run("unscannable", testExec(testCase{impl: g, command: "foo bar"}, "non-empty interface", "")) + }) + }) +} diff --git a/tools/tools.go b/tools/tools.go index ed051d7..e7cc796 100644 --- a/tools/tools.go +++ b/tools/tools.go @@ -180,7 +180,7 @@ func Exec(o ExecOptions, function string, args ...string) error { cacheDir := o.CacheDir if cacheDir == "" { - path.Join(os.Getenv("HOME"), ".wand") + cacheDir = path.Join(os.Getenv("HOME"), ".wand") } functionDir := path.Join(cacheDir, functionHash) @@ -204,6 +204,7 @@ func Exec(o ExecOptions, function string, args ...string) error { } goGet := func(pkg string) error { + println("go get", pkg) if err := execInternal("go get", pkg); err != nil { return fmt.Errorf("failed to get go module: %w", err) } diff --git a/wand.go b/wand.go index e2bcc63..2335a3c 100644 --- a/wand.go +++ b/wand.go @@ -11,6 +11,7 @@ type Config struct { merge []Config fromOption bool optional bool + test string } type Cmd struct { @@ -23,9 +24,11 @@ type Cmd struct { shortForms []string description string isHelp bool - helpRequested bool + version string } +// name needs to be valid symbol. The application name should also be a valid symbol, +// though not mandatory. If it is not, the environment variables may not work properly. func Command(name string, impl any, subcmds ...Cmd) Cmd { return command(name, impl, subcmds...) } @@ -53,6 +56,15 @@ func ShortFormOptions(cmd Cmd, f ...string) Cmd { return cmd } +func Version(cmd Cmd, version string) Cmd { + cmd.subcommands = append( + cmd.subcommands, + Cmd{name: "version", version: version}, + ) + + return cmd +} + func MergeConfig(conf ...Config) Config { return Config{ merge: conf,