Pip, 65 60 bytes
OsX4FbPp:#_FIa^C X^Y"><+-.,[]"P[sX4pRXXsRA Uvbs(gU(y@?b)|9)]
The BF program and the nine explanation strings are taken as command-line arguments. Alternately, you can use the -r
flag to take them from stdin. Replit! Or, here's a 61-byte equivalent in Pip Classic: Try it online!
Former explanation
New explanation pending... This is the explanation for the previous 65-byte solution.
Oi:sX4Pp:#_FIa^C X^Y"><+-.,[]"WpP[iPBsX#xx:POpsX#Jps(gU(y@?x)|v)]
First, the setup:
Oi:sX4Pp:#_FIa^C X^Y"><+-.,[]" sX4 Space character, repeated 4 times i: Assign to i (the indent)O Output it without trailing newline Y"><+-.,[]" Yank that string into y (BF commands) ^ Split into a list of chars X Convert to a regex that matches any one of those chars C Wrap the regex in a capture group a^ Split the first program arg on that regex (As in Python, splitting on a regex wrapped in a group keeps the matches of the regex in the result list) FI Filter that list on this function: #_ Length of item (This gets rid of empty strings while not getting rid of "0", which is falsey in Pip) p: Assign the result to p (the processed program) P Print it with trailing newline
Then, the main loop:
WpP[iPBsX#xx:POpsX#Jps(gU(y@?x)|v)]Wp While p is not empty: P Print (with trailing newline) [ ] this list, concatenated: 1. Indent: x Last chunk (initially empty string) # Length of the above sX That many spaces PB Push those onto the end of i i (modifies i in-place) 2. Current chunk: POp Pop the first item from p x: Assign it to x 3. Padding: p Remaining chunks J Joined into a single string # Length of the above sX That many spaces s 4. One more space before explanation 5. Explanation: y@?x Index of current chunk in BF commands (0 to 7, or nil if not found) U( ) Increment (1 to 8, or nil) | Logical OR v Negative one (1 to 8, or -1) (g ) Item in program args at that index