Commit | Line | Data |
---|---|---|
752ae10d SBS |
1 | #!/bin/bash |
2 | # Desc: Generates Mediawiki subpage navigation links | |
3 | # Input: file text file with list of chapters | |
4 | # stdin text with list of chapters | |
5 | # Output: [[../Chapter 4|Next]], [[../Chapter 2|Previous]], [[../|Up]] | |
6 | # Version: 0.0.1 | |
7 | # Attrib: Steven Baltakatei Sandoval. (2024-01-29). reboil.com | |
8 | # License: GPLv3+ | |
9 | ||
10 | yell() { echo "$0: $*" >&2; } # print script path and all args to stderr | |
11 | die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status | |
12 | must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails | |
13 | read_input() { | |
14 | # Note: May accept specified file or stdin, but not both | |
15 | # Input: arg input text (newline delimited) | |
16 | # stdin input text (newline delimited) | |
17 | # Output: stdout output text (newline delimited) | |
18 | # Depends: BK-2020-03 read_stdin (v0.1.1), yell(), die() | |
19 | ||
20 | # Parse args | |
21 | ## Only 1 argument. | |
22 | if [[ "$#" -gt 1 ]]; then die "FATAL:Too many arguments ($#):$*"; fi; | |
23 | ## File specified. | |
24 | if [[ "$#" -eq 1 ]] && [[ -f "$1" ]] && [[ ! -p /dev/stdin ]]; then | |
25 | while read -r line; do | |
26 | printf "%s\n" "$line"; | |
27 | done < "$1" && return 0; fi; | |
28 | if [[ "$#" -eq 0 ]] && [[ -p /dev/stdin ]]; then | |
29 | read_stdin && return 0; fi; | |
30 | die "FATAL:Unknown error."; | |
31 | }; | |
32 | read_stdin() { | |
33 | # Desc: Consumes stdin; outputs as stdout lines | |
34 | # Input: stdin (consumes) | |
35 | # Output: stdout (newline delimited) | |
36 | # return 0 stdin read | |
37 | # return 1 stdin not present | |
38 | # Example: printf "foo\nbar\n" | read_stdin | |
39 | # Depends: GNU bash (version 5.1.16), GNU Coreutils 8.32 (cat) | |
40 | # Version: 0.1.1 | |
41 | # Attrib: Steven Baltakatei Sandoval (2024-01-29). reboil.com | |
42 | local input_stdin output; | |
43 | ||
44 | # Store stdin | |
45 | if [[ -p /dev/stdin ]]; then | |
46 | input_stdin="$(cat -)" || { | |
47 | echo "FATAL:Error reading stdin." 1>&2; return 1; }; | |
48 | else | |
49 | return 1; | |
50 | fi; | |
51 | ||
52 | # Store as output array elements | |
53 | ## Read in stdin | |
54 | if [[ -n $input_stdin ]]; then | |
55 | while read -r line; do | |
56 | output+=("$line"); | |
57 | done < <(printf "%s\n" "$input_stdin") || { | |
58 | echo "FATAL:Error parsing stdin."; return 1; }; | |
59 | fi; | |
60 | ||
61 | # Print to stdout | |
62 | printf "%s\n" "${output[@]}"; | |
63 | ||
64 | return 0; | |
65 | }; # read stdin to stdout lines | |
66 | validate_subpage_list() { | |
67 | # Desc: Check for illegal characters in subpage titles | |
68 | # Input: stdin unvalidated subpage list | |
69 | # Output: stdout validated subpage list | |
70 | # Depends: BK-2020-03 read_stdin(), yell(), die() | |
71 | # GNU sed v4.8 | |
72 | while read -r line; do | |
73 | ||
74 | # Reject chars illegal in Mediawiki page titles. | |
75 | re_illegal='[][><|}{#_]'; # match illegal page names chars #, <, >, [, ], _, {, |, } | |
76 | if [[ "$line" =~ $re_illegal ]]; then | |
77 | die "FATAL:Illegal char. Not allowed: #, <, >, [, ], _, {, |, }:$line"; | |
78 | fi; | |
79 | ||
80 | # Reject trailing spaces. | |
81 | re_ts=' $'; # match trailing space | |
82 | if [[ "$line" =~ $re_ts ]]; then | |
83 | die "FATAL:Trailing spaces not allowed:$line"; | |
84 | fi; | |
85 | ||
86 | # Replace some chars with HTML-style codes | |
87 | ## replace ampersand & with & # must be first | |
88 | ## replace double quote " with " | |
89 | ## replace single quote ' with ' | |
90 | line="$(sed \ | |
91 | -e 's/&/\&/g' \ | |
92 | -e 's/"/\"/g' \ | |
93 | -e "s/'/\'/g" \ | |
94 | <<< "$line" )" || { echo "FATAL:Error running sed."; }; | |
95 | printf "%s\n" "$line"; | |
96 | done || { | |
97 | echo "FATAL:Error reading stdin." 1>&2; return 1; }; | |
98 | }; | |
99 | generate_wikicode() { | |
100 | # Input: stdin validated subpage list | |
101 | # Output: stdout wikicode | |
102 | local lprev lnext; | |
103 | ||
104 | n=0; | |
105 | while read -r line; do | |
106 | #yell "$n:Processing line:$line"; # debug | |
107 | lprev="$lcurr"; | |
108 | lcurr="$lnext"; | |
109 | lnext="$line"; | |
110 | #declare -p lprev lcurr lnext; # debug | |
111 | ||
112 | # Skip first iteration | |
113 | if [[ "$n" -eq 0 ]]; then | |
114 | # yell "$n:DEBUG:Skipping first iteration."; # debug | |
115 | ((n++)); | |
116 | #printf -- "----\n" 1>&2; # debug | |
117 | continue; fi; | |
118 | ||
119 | # Handle first valid input set | |
120 | # yell "$n:DEBUG:Handling first valid input set."; # debug | |
121 | if [[ "$n" -eq 1 ]]; then | |
122 | printf "[[../%s|Next]], [[../|Up]]\n" \ | |
123 | "$lnext"; | |
124 | #printf -- "----\n" 1>&2; # debug | |
125 | ((n++)); continue; fi; | |
126 | ||
127 | # Handle middle lines | |
128 | # yell "$n:DEBUG:Handling middle lines."; # debug | |
129 | printf "[[../%s|Next]], [[../%s|Previous]], [[../|Up]]\n" \ | |
130 | "$lnext" "$lprev"; | |
131 | ((n++)); | |
132 | #printf -- "----\n" 1>&2; # debug | |
133 | done; | |
134 | ||
135 | # Handle last line | |
136 | lprev="$lcurr"; | |
137 | lcurr="$lnext"; | |
138 | lnext="$line"; | |
139 | printf "[[../%s|Previous]], [[../|Up]]\n" \ | |
140 | "$lprev"; | |
141 | ((n++)); | |
142 | }; | |
143 | main() { | |
144 | read_input "$@" | validate_subpage_list | generate_wikicode; | |
145 | }; # main program | |
146 | ||
147 | main "$@"; |