[Question]
  [
You are to take a string representing a piece of brainfuck code and Explanations, containing only printable ASCII characters and newlines ( to `~`, ASCII 10 and 32 to 126) as input and output an explanation of that code, formatted to be compliant with Stack Exchange markdown.
That is, the explanation must satisfy:
* Each line has an additional leading space, or multiple if the line above has multiple characters of code, such that it remains aligned vertically
* All commands are on their own line, while any consecutive no-ops (anything that isn't one of `<>+-.,[]`) are grouped together on one line
* The "explanation" for each command are all aligned to a single column, one space after the code itself
* The entire thing is in a "code block".
	+ Either the entire explanation has a preceding and trailing ````` line, or
	+ The entire explanation has a preceding `<pre><code>` line and a trailing `</code></pre>`
	+ Each line of the explanation has 4 leading spaces, in addition to any leading spaces it might already have.
	+ You don't have to escape parts of the output that might break the markdown.
* The first line of code block is the BF input code.
For example, if the code is `+[]Loop`, the explanation (without "explanations") would be formatted as one of
```
    +[]Loop
    +      
     [     
      ]    
       Loop
```
  
```
<pre><code>+[]Loop
+      
 [     
  ]    
   Loop
</code></pre>
```
  
```
```
+[]Loop
+      
 [     
  ]    
   Loop
```
```
### Explanations
The explanation for each character will be provided as input:
```
Move the pointer to the right
Move the pointer to the left
Increment the memory cell at the pointer
Decrement the memory cell at the pointer
Output the character signified by the cell at the pointer
Input a character and store it in the cell at the pointer
Jump past the matching ] if the cell at the pointer is 0
Jump back to the matching [ if the cell at the pointer is nonzero
No Operation
```
The input always contain 9 explanation strings.  
Answers can choose how to associate each brainfuck command with each explanation.  
You may use array.  
We can now add these explanations to our sample code to get
```
    +[]Loop
    +       Increment the memory cell at the pointer
     [      Jump past the matching ] if the cell at the pointer is 0
      ]     Jump back to the matching [ if the cell at the pointer is nonzero
       Loop No Operation
```
(using 4 leading spaces instead of backtick fencing or HTML tags).
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest code in bytes wins.
## Testcases
Input:
```
[]<>{}()++--..,,
Move the pointer to the right
Move the pointer to the left
Increment the memory cell at the pointer
Decrement the memory cell at the pointer
Output the character signified by the cell at the pointer
Input a character and store it in the cell at the pointer
Jump past the matching ] if the cell at the pointer is 0
Jump back to the matching [ if the cell at the pointer is nonzero
No Operation
```
Output:
```
    []<>{}()++--..,,
    [                Jump past the matching ] if the cell at the pointer is 0
     ]               Jump back to the matching [ if the cell at the pointer is nonzero
      <              Move the pointer to the left
       >             Move the pointer to the right
        {}()         No Operation
            +        Increment the memory cell at the pointer
             +       Increment the memory cell at the pointer
              -      Decrement the memory cell at the pointer
               -     Decrement the memory cell at the pointer
                .    Output the character signified by the cell at the pointer
                 .   Output the character signified by the cell at the pointer
                  ,  Input a character and store it in the cell at the pointer
                   , Input a character and store it in the cell at the pointer
```
Input:
```
Brainfuck Power.
Move the pointer to the right
Move the pointer to the left
Increment the memory cell at the pointer
Decrement the memory cell at the pointer
Output the character signified by the cell at the pointer
Input a character and store it in the cell at the pointer
Jump past the matching ] if the cell at the pointer is 0
Jump back to the matching [ if the cell at the pointer is nonzero
No Operation
```
Output:
```
```
Brainfuck Power.
Brainfuck Power  No Operation
               . Output the character signified by the cell at the pointer
```
```
Input:
```
>++++++[{{<,.>-}}]
Move the pointer to the right
Move the pointer to the left
Increment the memory cell at the pointer
Decrement the memory cell at the pointer
Output the character signified by the cell at the pointer
Input a character and store it in the cell at the pointer
Jump past the matching ] if the cell at the pointer is 0
Jump back to the matching [ if the cell at the pointer is nonzero
No Operation
```
Output:
```
<pre><code>>++++++[{{<,.>-}}]
>                  Move the pointer to the right        
 +                 Increment the memory cell at the pointer           
  +                Increment the memory cell at the pointer
   +               Increment the memory cell at the pointer
    +              Increment the memory cell at the pointer
     +             Increment the memory cell at the pointer
      +            Increment the memory cell at the pointer
       [           Jump past the matching ] if the cell at the pointer is 0
        {{         No Operation
          <        Move the pointer to the left
           ,       Input a character and store it in the cell at the pointer
            .      Output the character signified by the cell at the pointer
             >     Move the pointer to the right
              -    Decrement the memory cell at the pointer
               }}  No Operation
                 ] Jump back to the matching [ if the cell at the pointer is nonzero
</code></pre>
```
Input:
```
><+-.,NOP[]
Move
Move
Increment
Decrement
STD
STD
While
While
NOP
```
Output:
```
    ><+-.,NOP[]
    >           Move
     <          Move
      +         Increment
       -        Decrement
        .       STD
         ,      STD
          NOP   NOP
             [  While
              ] While
```
Input:
```
-\
Blah
Blah
Blah
Decrement
Blah
Blah
Blah
Blah
Nothing happens here
```
Output:
```
-\
-  Decrement
 \ Nothing happens here
```
  
[Answer]
# [brainfuck](https://github.com/TryItOnline/brainfuck), ~~811~~ ~~775~~ ~~709~~ 701 bytes
```
>>-[-[--->]<<-]>--...<++++++++++.>>>>>>>>>>+[->>>>>>+<<,[[-<+<+>>]<----------[[-]->]-[+>-]<<<+[-<[-]>]<[-<+>>+<]++++++[->-------<]>>++++++[-<<++++++>>]>+<<-[<->>]>[<]<-[<------->>]>[<]<-[<-->>]>[<]<-[<-------->>]>[<]<--------------[<--->>]>[<]<--[<---->>]>[<]+++++[-<------>]<+[<----->>]>[<]<--[<------>>]>[<]<[-]<<+>[>>>-]<[>>>]<<<->>++++[->++++++++<]+>>>+>]<]+[<<<<<<]>>>>[.>>>>>>]>>>>-<<<<<<<<<<[<<<<<<]<<<<<.>>>+[->>>>>>>>>>>>>[>>>>>>]<<<<<[<[<<.<<<<]>>>>>>[>>>>>>]<<<<<.>>>>[>+>>>>>[<<<<.>>>>>+>>>>>]<<<<[>>>.>>>]>>>.>>>[.>>>>>>]>>[<<<<<<]<]<<<[>->>>+>[>>>.>>>]>>-<<<<<.<[<<<<<<]<[->>>>>>>[>>>>>>]+>>>>[>>>>>>]>>-<<<<<<[<<<<<<]<]>+[>>>>>>]+>>>>[.>>>>>>]>>[<<<<<<]<<<<]+<<<.>>]>]>[<<<<<<]<<<<<<...
```
[Try it online!](https://tio.run/##bVJNT8MwDL33r2TOL7BygQsSAomr5QNMGUxAW432NO23j5fESduBKzXO8/Pzh/J2ej32h3n/eb2GQIKPKCgzaSDy3rNr5kMzJ2QO806E2LELSKNmABVCJC4Q5BgZDAicxE6JWlShZCmsgA1jqwvRVIOEKbnCmv1iG@RveIE2luNLqNDtXqtbvqJtvpGq8hWRNJ4LgmXAS0cal8ooGK5uD@JpX4gqRLNp2qDYWvOFuFnl5L9f79xMLM/Y4PsmehP1BXEl0hADMifxvbXht221TjTzKCeu@KVpv3TcGq1NuPWlTbnoYrYN85/a6edK45o3v9oO453i@drbOZ955wNdLto9DTSM3UO/P8Xv2E/dfazeYzxM3cvx/WPqnsfYd3dfw08Ec5wBzBOOXw "brainfuck ‚Äì Try It Online")
This could probably be golfed more, as this is, like, the second brainfuck program I've written.
## Explanation
I should really write a program to do this for me...
[Fullscreen Explanation](https://pastebin.com/raw/3qAzHtbm)
```
#####
# Execution will be divided into two phases: input and output.
# The input phase will input all characters and lay them out into memory with metadata.
# The output phase will then loop over the memory and print various segments of it, forming the explanation.
###############
# Input Phase #
###############
#####
# First, let's take a look at the memory layout.
# We'll divide the memory into 6-byte chunks.
# The chunks will be laid out in this format:
#   - first header chunk, to denote the start
#   - second header chunk, to denote the start
#   - first source chunk
#   - second source chunk
#   - ...
#   - last source chunk
#   - primary separator chunk (in place of newline)
#   - first chunk of first explanation
#   - second chunk of first explanation
#   - ...
#   - last chunk of first explanation
#   - separator chunk (in place of newline)
#   - first chunk of second explanation
#   - ......
#   - last chunk of last explanation
#   - eof chunk
# The first header chunk will have the following bytes:
#   0 10 96 0 0 0
# (10 is newline, and 96 is backtick)
# The second header chunk will consist entirely of zeroes.
                     #####
                     # Initialize the header chunks and output the initial code fence:
>>                     # Move to cell #2 (0-indexed).
-[-[--->]<<-]>--       # Set cell #2 to backtick (96) (pulled from https://esolangs.org/wiki/Brainfuck_constants).
...                    # Print it thrice (fine, there is a tiny bit of output in this phase).
<++++++++++.           # Set cell #1 to newline (10) and print it.
>>>>>>>>>>+          # Move to cell #5 of the second header chunk and temporarily set it to 1.
                     #####
                     # Next, read the input into chunks and initialize them.
                     # Every non-header non-eof chunk will be initialized to the following format:
                     #   #0: [char]  (0 if separator)
                     #   #1: [kind]  (which operator the char is)
                     #   #2: [mark]  (currently 1; this will occasionally be temporarily set to 0 as a "bookmark")
                     #   #3: 32      (the code for space, used for output)
                     #   #4: [noop]  (1 if no-op source chunk or non-primary separator, 0 otherwise)
                     #   #5: [done]  (currently 0, undone)
                     # During the initialization, some cells are used for temporary values.
[                    # While the current cell (#5 of the preceding chunk) is non-zero (and thus known to be 1), loop over the input:
  -                    # Subtract 1 from the cell, [done], returning it to 0 (undone)
  >                    # Move to the active chunk.
                       # Cell #5 will be used for positioning the pointer after a branch ('alignment'):
  >>>>>+               # Set cell #5 to 1
                       #####
                       # Next, we'll read a character.
  <<,                  # Move to cell #3 and input a character into it (temp).
  [                    # If this character is non-zero (not eof):
    [-<+<+>>]            # Duplicate this character into cells #1 and #2 [temp], erasing this cell, #3.
    <----------          # Move to cell #2 and subtract 10 (code for newline) from it.
                         # The chunk is now:
                         #   #0: 0
                         #   #1: char (temp)
                         # > #2: char - 10 (temp)
                         #   #3: 0
                         #   #4: 0
                         #   #5: 1 (alignment)
                         #####
                         # Next, if char is newline (10), we'll set cell #1 to 0.
    [[-]->]              # If cell #2 (char - 10) is non-zero (the char is not a newline), set this cell to 255 and move to cell #3.
    -[+>-]               # Move to the first cell to the right set to 1 (cell #5), and set it to 0.
                         # (The above is done without any net change to other cells.) 
    <<<+                 # Move to cell #2 and add one to it; this cell is now 1 if char is a newline, or 0 otherwise.
    [-<[-]>]             # If cell #2 is 1, set it back to 0, move to cell #1, clear it, and move back to cell #2.
                         # From now on, char will be 0 if the character was a newline.
                         # The chunk is now:
                         #   #0: 0
                         #   #1: char (temp)
                         # > #2: 0
                         #   #3: 0
                         #   #4: 0
                         #   #5: 0
                         #####
                         # Next we'll inialize cell #0 [char] and put a copy of char into cell #2.
    <                    # Move to cell #1.
    [-<+>>+<]            # Duplicate this value to cells #0 and #2, clearing this cell.
                         # The chunk is now:
                         #   #0: [char]
                         # > #1: 0
                         #   #2: char (temp)
                         #   #3: 0
                         #   #4: 0
                         #   #5: 0
                         #####
                         # Next, we'll initialize cell #1 [kind] to a number denoting the 'kind' of the char is.
                         # The kind is an index from 0 to 8 matching the order "N+-<>[],." (where N stands for any no-op).
                         # The kind could be determined by directly checking if the character matches an operation (char == op).
                         # In BF, however, it's easier to check if something is not equal to X than if it is equal to X.
                         # We'll start cell #1 [kind] at the sum of the kind, 36 (1+2+3+4+5+6+7+8).
                         # For each operation, we'll check if the character does not match that operation, (char != op).
                         # To do so, we will use cell #2 for checking whether (char - op) is non-zero.
                         # If the character does not match that operation, we will subtract its kind from the sum.
                         # After doing so for all of the operations, the result will be the kind of the operation that the character matches.
                         # We'll do this not in kind order, but in op order: "+" (43), then "," (44), then "-" (45), etc.
                         #####
>>++++++[-<<++++++>>]    # Set cell #1 to 36 and move to cell #3.
>+                       # Set cell #4 to 1 to be used for alignment.
                         # The chunk is now:
                         #   #0: [char]
                         #   #1: 36 (sum of all kinds)
                         #   #2: char (char - 0)
                         #   #3: 0
                         # > #4: 1 (alignment)
                         #   #5: 0
                         #####
                         # The next set of lines are based on using the following pattern for each of the operations:
                           # Subtract from cell #2 the difference between the char codes for this operation and the previous.
                           # If cell #2 is not zero (if char != op):
                             # Remove this kind from the sum by subtracting from cell #1 (kind_sum) the kind of this operation.
                           # Return to cell #2 (using cell #4 for alignment).
                           # The resulting chunk will be:
                           #   #0: [char]
                           #   #1: kind_sum
                           # > #2: char (char - op)
                           #   #3: 0
                           #   #4: 1 (alignment)
                           #   #5: 0
                         # For '+', check 43:
    <++++++[-<------->]<-  # Subtract 43 (6 * 7 + 1) from cell #2, the difference between '+' and 0.
                           # The value in cell #2 is now char - 43.
    [                      # If the cell #2 is non-zero (char != 43; the character is not '+'):
      <->>                   # Subtract from cell #1 the kind of '+', 1.
    ]                      # End if.
    >[<]<                  # Return to cell #2 (using cell #4 for alignment).
                         # (For the remaining operations, the pattern will be shown in a condensed form.)
                         # For ',', check 44: 
    -                      # Subtract 1 (the difference between ',' and '+').
    [<------->>]>[<]<      # If not zero, remove 7 from kind_sum. Return to cell #2.
                         # For '-', check 45:
    -                      # Subtract 1.
    [<-->>]>[<]<           # If not zero, remove 2 from kind_sum. Return to cell #2.
                         # For '.', check 46: 
    -                      # Subtract 1.
    [<-------->>]>[<]<     # If not zero, remove 8 from kind_sum. Return to cell #2.
                         # For '<', check 60:
    --------------         # Subtract 14.
    [<--->>]>[<]<          # If not zero, remove 3 from kind_sum. Return to cell #2.
                         # For '>', check 62:
    --                     # Subtract 2.
    [<---->>]>[<]<         # If not zero, remove 4 from kind_sum. Return to cell #2.
                         # For '[', check 91
    >+++++[-<------>]<+    # Subtract 29 (5 * 6 - 1).
    [<----->>]>[<]<        # If not zero, remove 5 from kind_sum. Return to cell #2.
                         # For ']', check 93
    --                     # Subtract 2.
    [<------>>]>[<]<       # If not zero, remove 6 from kind_sum. Return to cell #2.
                         #
    [-]                  # Set cell #2 to zero.
                         # The chunk is now:
                         #   #0: [char]
                         #   #1: [kind]
                         # > #2: 0
                         #   #3: 0
                         #   #4: 1 (temp)
                         #   #5: 0
                         #####
                         # Next, cell #4 [noop] will be initialized to 0 if char is not a no-op.
    <<+                  # Move to cell #0, adding 1 (temporarily, for alignment)
    >                    # Move to cell #1.
    [>>>-]               # If cell #1 [kind] is non-zero (the char is not a no-op),
                         #  move to cell #4 [noop] and subtract 1 to set it to 0.
    <[>>>]               # Move to cell #3, using cell #0 for realignment.
    <<<-                 # Move to cell #0 and subtract 1 from it, returning it to char.
                         # The chunk is now:
                         # > #0: [char]
                         #   #1: [kind]
                         #   #2: 0
                         #   #3: 0
                         #   #4: [noop] (1 if no-op, 0 otherwise)
                         #   #5: 0
                         #####
                         # Next, cell #2 [mark] will be initialized to 1 (unmarked) and cell #3 [space] will be initialized to 32 (code for space).
    >>++++[->++++++++<]  # Move to cell #2 and set cell #3 to 32 (4 * 8)
    +                    # Set #2 [mark] to 1 (unmarked)
    >>>+                 # Move to cell #5 and set it to 1 (temporarily, so the input loop continues; this will be unset in the next iteration).
    >                    # Move to cell #0 of the next chunk.
  ]                    # End "if non-eof".
  <                  # If at cell #0 of the next chunk (from the preceding branch for processing a source chunk), move to cell #5 of the current chunk;
                     #   otherwise (at cell #3 after the source chunks), move to cell #2.
]                    # End input loop.
                     # Every non-header non-eof chunk is now:
                     #   #0: [char]  (0 if separator)
                     #   #1: [kind]  (which operator the char is)
                     #   #2: [mark]  (currently 1; this will occasionally be temporarily set to 0 as a "bookmark")
                     #   #3: 32      (the code for space, used for output)
                     #   #4: [noop]  (1 if no-op source chunk or non-primary separator, 0 otherwise)
                     #   #5: [done]  (currently 0, undone)
                     # Since the loop ended, it reached eof, and the head is at cell #2 of the eof chunk.
################
# Output Phase #
################
                     #####
                     # First, we will return to the header chunks.
+                    # Set cell #2 to 1 (used later to save a byte).
[<<<<<<]             # Move left one chunk at a time until cell #2 is zero, reaching the second header chunk.
>>>>                 # Move to cell #0 of the first source chunk.
[.>>>>>>]            # While cell #0 is non-zero, print it and move to the next chunk 
                     #  (this writes the first line of the explanation, the code verbatim).
                     # Now, the head is at cell #0 of the primary separator chunk.
>>>>-<<<<            # Set its cell #4 to 0 (used later to break a loop).
<<<<<<[<<<<<<]       # Move to the next 0-char chunk to the left (this is the second header chunk).
<<<<<.               # Move to cell #1 of the first header chunk (newline) and output it (ending the first line).
                     #####
                     # As we go through each line of the explanation, we'll follow this psuedo-code:
                     #   - Output a space for every source character marked as 'done'
                     #   - Output the characters for the active operations (multiple if it's a chain of no-ops, only one otherwise)
                     #   - Mark all active operations 'done'
                     #   - Output a space for every source character after the active ones
                     #   - Output a space followed by the associated explanation
                     # These steps will be expanded on later.
>>>                  # Move to cell #4 of the first header chunk.
+                    # Set it to one to start the loop.
[                    # Begin a loop to print subsequent lines:
                       #####
                       # First, we will find the first not done chunk.
  -                    # Set this cell, #4 of the first header chunk, back to 0.
  >>>>>>>>>>>>>        # Move to cell #5 [done] of the first source chunk.
  [>>>>>>]             # Go to the first not done cell to the right (it might be the current chunk).
  <<<<<                # Go to cell #0 [char].
  [                    # If it's non-zero (if it's a source chunk):
                         #####
                         # Next, we will output the leading spaces and the first active character.
    <[<<.<<<<]           # Go to cell #5 of the first not done chunk to the left
                         #  (this is the second header chunk), outputting spaces along the way.
    >>>>>>               # Go to cell #5 [done] of the next chunk.
    [>>>>>>]             # Move to cell #5 of the first non-done cell to the right.
    <<<<<.               # Move to cell #0 [char] of this chunk (the first active source chunk) and output it.
    >>>>                 # Move to cell #4 [noop] of this chunk.
  
                         #####
                         # Next, the following branch will process a sequence of no-op chunks. 
                         # This is handled differently from non-no-op chunks because sequential no-op characters are printed in one line.
    [                    # If it's non-zero (if this character is a no-op):
      >+                   # Set cell #5 [done].
                           #####
                           # First, we will output each subsequent active character and mark their chunks as done.
      >>>>>                # Move to cell #4 [noop] of the next chunk.
      [                    # While the current chunk is a no-op:
        <<<<.                # Move to cell #0 [char] and output it.
        >>>>>+               # Move to cell #5 [done] and set it to 1.
        >>>>>                # Move to cell #4 [noop] of the next chunk.
                             # (Note that the primary separator has cell #4 [noop] set to 0 in order to break this loop)
      ]                    # End loop. Now the head is at the cell #4 [noop] of the first non-no-op chunk.
                           #####
                           # Next, we will output the trailing spaces and the no-op explanation.
      <<<<[>>>.>>>]        # Move to the primary separator chunk, outputting a space for each skipped chunk.
      >>>.>>>              # Move to cell #0 of the first chunk of the first explanation, outputting a space.
      [.>>>>>>]            # Move to the next non-explanation chunk, outputting each character.
      >>                   # Move to cell #2 [mark].
      [<<<<<<]             # Move to cell #2 of the second header chunk.
      <                    # Move to cell #1.
    ]                    # End if.
    <<<                  # If at cell #1 of the second header chunk (from the preceding branch for processing a no-op), move to cell #4 of the first header chunk;
                         #  otherwise, (still at the cell $4 [noop] of the current source chunk), move to cell #1 [kind].
                         #####
                         # Next, the following branch will process a non-no-op chunk.
                         # This is handled separately from no-op chunks because operators are printed on separate lines.
    [                    # If cell #1 [kind] is non-zero (if in a non-no-op source chunk):
                           #####
                           # First, we will output the trailing spaces and find the primary separator chunk.
      >-                   # Move to cell #2 [mark] and set it to 0 (this marks the cell to return to later).
      >>>+                 # Move to cell #5 [done] and set it to 1.
      >[>>>.>>>]           # Move to the primary separator chunk, outputting a space for each skipped chunk.
      >>-                  # Mark this chunk (the primary separator chunk).
      <<<<<.<              # Move to cell #2 [mark] of the previous chunk, outputting a space.
      [<<<<<<]             # Move to the first marked (mark == 0) cell to the left (the active source chunk).
      <                    # Move to cell #1 [kind].
                           #####
                           # Next, we'll locate the correct explanation.
                           # We're at cell #2 [kind], which acts as an index to the explanation.
                           # The primary separator (which precedes the 0th (no-op) explanation) is marked.
      [-                   # Continually decrement the kind:
                             # Each iteration will unmark the currently marked separator and mark the next separator.
        >>>>>>>[>>>>>>]      # Move to the first marked cell to the right.
        +                    # Unmark this chunk.
        >>>>                 # Move to cell #0 of the next chunk.
        [>>>>>>]             # Move through the explanation chunks to the next separator chunk.
        >>-                  # Mark this separator chunk.
        <<<<<<[<<<<<<]<      # Return cell #1 [kind] of the active source chunk (as it's marked).
      ]                    # End loop.
                           #####
                           # Next, we will output the explanation we have located.
      >+                   # Unmark the current source chunk.
      [>>>>>>]             # Move to the marked separator chunk.
      +                    # Unmark this chunk.
      >>>>                 # Move to cell #0 [char] of the next chunk.
      [.>>>>>>]            # While cell #0 [char] is non-zero, output it and move to the next chunk.
      >>[<<<<<<]           # Return to the second header chunk.
      <<<<                 # Move to cell #4 of the first header chunk.
    ]                    # End if.
                         # From either branch, we are now at cell #4 of the first header chunk.
    +                    # Set cell #4 to 1 (to continue the loop).
    <<<.                 # Move to cell #1 (newline) and output it.
    >>                   # Move to cell #3 (which is 0).
  ]                    # End if.
  >                    # If at the first header chunk (from the preceding branch for processing a source chunk), move to cell #4 (which is 1, continuing the loop);
                       #  otherwise (still at the primary separator), move to cell #1 (which is 0, ending the loop).
]                    # End loop.
#####
# Lastly, we will print the final code fence.
>[<<<<<<]            # Move to cell #2 of the second header chunk.
<<<<<<...            # Move to the first header chunk and output the backtick thrice.
#####
# Finally, we can enjoy the fruits of our efforts: https://pastebin.com/raw/C9yYHx3F.
```
[Answer]
# [Vyxal](https://github.com/Vyxal/Vyxal) `oj`, 69 bytes
```
:4$Íòç,`([%^])`\\`><+-,.[]`f:‚Üí+‚àë%·π°';:vL¬¶0p·π™Z∆õ√∑$Íòçnh‚Üê=Tuw‚à®‚ñ°·∏£‚àá‚Äüƒ∞‚ÄûL‚Ä∫‚Äû‚Ü≤p4$Íòç‚àë
```
[Try it Online!](https://lyxal.pythonanywhere.com?flags=oj&code=%3A4%24%EA%98%8D%2C%60%28%5B%25%5E%5D%29%60%5C%5C%60%3E%3C%2B-%2C.%5B%5D%60f%3A%E2%86%92%2B%E2%88%91%25%E1%B9%A1%27%3B%3AvL%C2%A60p%E1%B9%AAZ%C6%9B%C3%B7%24%EA%98%8Dnh%E2%86%90%3DTuw%E2%88%A8%E2%96%A1%E1%B8%A3%E2%88%87%E2%80%9F%C4%B0%E2%80%9EL%E2%80%BA%E2%80%9E%E2%86%B2p4%24%EA%98%8D%E2%88%91&inputs=%3E%2B%2B%2B%2B%2B%2B%5B%7B%7B%3C%2C.%3E-%7D%7D%5D%0AMove%20the%20pointer%20to%20the%20right%0AMove%20the%20pointer%20to%20the%20left%0AIncrement%20the%20memory%20cell%20at%20the%20pointer%0ADecrement%20the%20memory%20cell%20at%20the%20pointer%0AOutput%20the%20character%20signified%20by%20the%20cell%20at%20the%20pointer%0AInput%20a%20character%20and%20store%20it%20in%20the%20cell%20at%20the%20pointer%0AJump%20past%20the%20matching%20%5D%20if%20the%20cell%20at%20the%20pointer%20is%200%0AJump%20back%20to%20the%20matching%20%5B%20if%20the%20cell%20at%20the%20pointer%20is%20nonzero%0ANo%20Operation&header=&footer=)
## Explained
```
`([%^])`
```
Push the string `"([%^])"` to the stack. This will serve as the basis for a
regular expression that groups on non-BF commands
```
\\
```
Push a backslash to the stack. This will serve to escape all the characters in
the BF character set (`[` and `]` need to be escaped, because they interfere with the range set)
```
`><+-,.[]`f
```
Push the string `"><+-,.[]"` to the stack, and turn it into a list of characters.
It's important it's turned into a list of characters because the backslash will
be prepended to each character using vectorised addition.
```
:‚Üí
```
But first, put the character set into the ghost variable for later storage -
there's no BF character set element in vyxal, so to save bytes, it needs to be
stored.
```
+‚àë
```
Prepend the backslash to each character just like I said I would, and convert it
back to a single string.
```
%
```
And place that into the regex pattern string from earlier using string formatting
```
·π°';
```
Split the input program on that regex, and keep only non-empty strings. This splits
the program into single bf chars and groups of NOPs.
```
:vL¬¶0p·π™Z
```
Get the length of each group, get the cumulative sum of that, prepend a 0 and zip
with each group. This has the effect of calculating how many spaces to prepend to
each group.
```
∆õ
```
To each item `X = [spaces, character_group]` in that, do the following
```
√∑√∞*p
```
Prepend `spaces` spaces to `character_group`
```
nh‚Üê=Tuw‚à®
```
Get the index of `character_group` in the BF character set stored in the
ghost variable. This is basically a hacky version of `·∏ü` because `·∏ü` doesn't
work on the version the site uses (it's fixed in the 2.6 preleases, but I'm
sticking with 2.4.1)
```
‚ñ°·∏£
```
Wrap all inputs (program and explanation strings) into a single list and push
the program separately from the explanation strings.
```
‚àá‚Äüƒ∞
```
Do some weird stack manipulation to retrieve the corresponding explanation
string using the index generated by `nh‚Üê=Tuw‚à®`.
```
‚ÄûL‚Ä∫‚Äû‚Ü≤$+
```
Left justify the character group with the prepended spaces with extra spaces
to match the length of the input program + 1. And add that to the explanation
using some extra weird stack manipulation.
```
4√∞*p‚àë
```
Indent that 4 spaces, and convert into a single string.
```
;‚Åã
```
Join the entire list on newlines. The `j` flag would usually take care of this,
but 69 is a funny number.
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/wiki/Commands), ~~53~~ ~~52~~ 50 [bytes](https://github.com/Adriandmen/05AB1E/wiki/Codepage)
```
.Œ≥"><+-.,[]"¬©s√•N>*}DU¬πg>j|VŒµXN>¬£Jv√Å}Y¬ÆXN√®k√®¬´}¬π≈°4√∫¬ª
```
-2 bytes thanks to *@ovs*.
Outputs the lines with four leading spaces.
[Try it online.](https://tio.run/##jdC/S8NAFAfwPX/Fo5OaHzg4lkxdWjCdlErIcLm@JmeTu3B3KVTN4J8iIlQEF3Gobhdc@y9F2qh0MOj43vd9eI8nFIkZNo23een5fdv1nDDqmUdVPwT@UTU4M@vEv7w537xOAt/cjxb1bXVhnidBvZrXK/NUmfXH3Un9Zt6bJoz6/nV1cGjbrut5jmOdigWCThEKwbhGCVrsSsmSVHemGc60NeRUYo5c71o55kIugWKWAdH7yBrgPwfHpS7KtkVTIgndrlQs4WzGcArxso1@kUO@hWSPET4FpYVEYBoY75SjMi@gIOrrOKJpyngCEbBZlwGm4LiFMaHz76f82PAPywW/QimsQMC4QEk0E/wT)
**Explanation:**
```
.Œ≥                 # Group the first (implicit) input-string into parts:
  "><+-.,[]"       #  Push the string "><+-.,[]"
            ¬©      #  Store it in variable `¬Æ` (without popping)
             s     #  Swap to get the current character
              √•    #  Check if it's in the string
               N>* #  Multiply it by the 1-based index
                   #  (this ensures all characters in that string become unique
                   #  values, but all unknown characters map to the same value 0)
}DU                # After the group-by, store a copy in variable `X`
   ¬πg              # Push the length of the first input-string
     >             # Increase it by 1
      j            # Make all strings of that length by padding leading spaces
|                  # Push a list of all remaining input-lines
 V                 # Pop and store it in variable `Y`
      Œµ            # Map over the parts:
       X           #  Push the parts from variable `X`
        N>¬£        #  Leave the first map-index + 1 amount of parts
           J       #  Join them together
            v }    #  Pop and loop its length amount of times:
             √Å     #   Rotate the string once towards the right
         XN√®       #  Get the map-index'th part from variable `X`
        ¬Æ   k      #  Get the index of that part from variable `¬Æ`
       Y     √®     #  Use that to index into the list of lines `Y`
              ¬´    #  Append the two strings together
      }¬π≈°          # After the map: prepend the first input-string
         4√∫        # Pad each string with 4 leading spaces
           ¬ª       # Join the list by newlines
                   # (after which the result is output implicitly)
```
[Answer]
# [Charcoal](https://github.com/somebody1234/Charcoal), ~~54~~ ~~48~~ 47 bytes
```
√ó ‚Å¥Ôº∞Ôº≥Ôº¶Œ∏¬´‚äûœÖ‚åï><+-.,[]Œπ¬ø‚Å∫¬≤Œ£‚úÇœÖ¬±¬≤‚ÜìÔº∞‚äüœÖŒπ¬ª‚Üë‚∏ø‚Üì‚âîÔº•‚ÅπÔº≥Œ∑Ôº•œÖ¬ßŒ∑Œπ
```
[Try it online!](https://tio.run/##VY9Ba8MwDIXPza8QOSnM3aHssnYMCmGQQ7pAOnboegipmhgc24vtbjD22z072aAzWDzQ06entm/GVjXC@2rk0uKeD2QwhZTBXZZtktIJy/XUKqR2trZBdxhbZzUCvmfwlSwqZ3p0DJ64PGH6@HCzvGWHY2DwaFzwM2AlnMEVg9oNWAveUvTvqGss4SoLD0p1IVzn6kPGGRKG4Gp7pTS6iTYH5UF@J7Nev2gG6duYxsDXlK0xvJNYNhrvGfw/gEEfHDMgGkKcrS3kiT6xn4JnG@/nU3bP1eE4kedSyHakgaRNcvpT9T6f/mvPBf3WMOeXF/ED "Charcoal ‚Äì Try It Online") Link is to verbose version of code. Explanation:
```
√ó ‚Å¥
```
Indent by 4 spaces.
```
Ôº∞Ôº≥
```
Print the code without moving the cursor.
```
Ôº¶Œ∏¬´
```
Loop over the characters in the code.
```
‚äûœÖ‚åï><+-.,[]Œπ
```
Push the index of the appropriate explanation to the predefined empty list. NOPs will have an index of `-1`, which will cyclically index to the last explanation, but is also useful for coalescing consecutive NOPs below.
```
¬ø‚Å∫¬≤Œ£‚úÇœÖ¬±¬≤
```
If there are not two consecutive NOPs, then...
```
‚Üì
```
... move down a line, else...
```
Ôº∞‚äüœÖ
```
... discard one of the NOPs.
```
Œπ
```
Output the current character.
```
¬ª‚Üë‚∏ø
```
Move to the start of the next column.
```
‚Üì
```
Move to the first row of explanations.
```
‚âîÔº•‚ÅπÔº≥Œ∑
```
Read in the explanations.
```
Ôº•œÖ¬ßŒ∑Œπ
```
Print each appropriate explanation.
Today I discovered a bug in Charcoal's `Split` command which unintentionally results in partial regex support: `Split(<string>, <list>)` is supposed to split the string at any occurrence of any word in `<list>`, but due to the bug what actually happens is that `Split(<pattern>, [<string>])` escapes the string and splits it on the pattern. Unfortunately the original approach has since been golfed down from its original 54 bytes which this approach ties with, but that's still good going considering the duplication of the command characters:
```
√ó ‚Å¥‚âîŒ¶‚™™‚Äú xMÔº¥¬¶Ôº¥~‚âß_x‚Äù‚ü¶Ôº≥‚üßŒπŒ∏Ôº∞‚™´Œ∏œâÔº¶Œ∏‚Å∫¬∂Œπ‚Üë‚∏ø‚Üì‚âîÔº•‚ÅπÔº≥Œ∑Ôº•Œ∏¬ßŒ∑‚åï><+-.,[]Œπ
```
[Try it online!](https://tio.run/##VY5Na8MwDEDv/RXGJ5k6O/WyrhQKoZBBu0A6dkhyCKnXGFzbcZx2h/13T4n3wQwSQpbeU9s1rjWNCiF3Uns4yasYgBLKyYqxp8VuGORFw14qLxwUVkkPtML3CWW92S4TXtYMh8tM29EXHiEXYDXjRGL0SDiMyks7w5@N1NBzcp/I78YR6BmJ3lyNqK00nRbxN3bXr5YTWjk6ccxNwDo1d/131qGx8MjJPzdqu1/ANIDCnc/0WXxAx8le6jPQ7WaZPODpUYfCEGLr@JKX9eyKKdOtE1eh/SIVP1VxSud466QS3xn3QnJTXw "Charcoal ‚Äì Try It Online") Link is to verbose version of code. Note: Backslashes are not supported because this is relying on buggy Charcoal behaviour. Explanation:
```
√ó ‚Å¥
```
Indent by 4 spaces.
```
‚âîŒ¶‚™™‚Äú xMÔº¥¬¶Ôº¥~‚âß_x‚Äù‚ü¶Ôº≥‚üßŒπŒ∏
```
Extract command characters or runs of non-command non-backslash characters from the input.
```
Ôº∞‚™´Œ∏œâ
```
Print the code without moving the cursor.
```
Ôº¶Œ∏‚Å∫¬∂Œπ
```
Output each command on its own line, but increasing the indent as it goes.
```
‚Üë‚∏ø
```
Move to the start of the next column.
```
‚Üì
```
Move to the first row of explanations.
```
‚âîÔº•‚ÅπÔº≥Œ∑
```
Read in the explanations.
```
Ôº•Œ∏¬ßŒ∑‚åï><+-.,[]Œπ
```
Find and output the appropriate explanation for each command, or the last explanation for non-commands.
[Answer]
# JavaScript (ES2022), 141 bytes
```
s=>a=>"    "+s+s.replace(/(?:[^+-.<>[\]]+|.)(?=(.*))/g,(c,e)=>`
`+(c+e.replace(/.|$/g,' ')).padStart(s.length+5)+a.at('><+-.,[]'.indexOf(c)))
```
[Try it online!](https://tio.run/##jVPfb9MwEH4mf8XRIdVeWqca4oH1x4TgZROjk9hbVzTXuSTeEjuyL4Wy7m8vTrrBJjFBHiL5@@67@3x3vpFr6ZXTNQ2NTXGXHL6O4BAuSrvJdFmCzeCDc3JzIAkyZ6uWLIhqf5wkuaaiWQllq4TU2/dJ7WxtvSyHDktJeo1DbVL8oU0@rJAKmx7UtuzStlk@2nrjdF4QMMXhaHQ0gku5gg90q42HMyfaoPPTS/isFRqP4ZhE89UNKhIpZtrgRaiHjjascyhCebK0qXEAfUn9AdxFAGtZNngMWWMUaWtAEjM8MK8ADEzhXFIhyAW2hbdbGI1bSmfADExgxENUPAUqtBclmpyK53wrMTB7FsHBITXOQGP2PtNO8wC2gQuzHAdv94Pw@@40yVUZPAYb2CJomgrdHstk6TtQWZPpvHFPQ@/5OIqy6c5PZ3I660H4erGPvXBYl1IhS9jJ8eJbPBST2eJquYy3grOTKROHnCf5gKkB8unsOrqOmYrxj0ps3wS6D33ORS3TryQdscfbxe94LEVoY382CZkHi2VfdGOeZ2GOnO@CU29LFKXNWcZ6i@VkdnfPeBwPh0IMBj3OrqNzu8bQCYTaakPogGx37PbhRbbEjKJToxxWaKiDKqys24DCsKqSnoqiT/ifgfOG6mYPqUI6qdqSXudGZxpTWG321F@Up6YVyicyaVLwZB2CJtDmReVZU9VQS/9gTpIqwjOBZbtZL2hAexjthSupbh@b8lu7@IfWWPMTnY2@WJiHZyPb5xBdh@XXFePC16UOM70yYeh8vPsF "JavaScript (Node.js) ‚Äì Try It Online")
```
f: (source_code: string) => (explain_array: string[]) => string
```
[Answer]
# [Pip](https://github.com/dloscutoff/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!](https://replit.com/@dloscutoff/pip) Or, here's a 61-byte equivalent in Pip Classic: [Try it online!](https://tio.run/##K8gs@P/fvzjCxC0poMBKOd7NMzHOWSEiLlLJzkZbV08nOlYpIBooXRAUEVEc5KitXZZUrJGura1R6WCfpFljqRn7/78BRKmff0B0rAFXUGZ6RgmXT2paCZdnXnJRam5qXgmXSyqM5V9aUlAKkgKR4RmZOalcQakFqYklXH75uvkF/3WLAA "Pip ‚Äì 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
```
[Answer]
# [Stax](https://github.com/tomtheisen/stax), 45 [bytes](https://github.com/tomtheisen/stax/blob/master/docs/packed.md#packed-stax)
```
√•‚ò∫m‚ñàQ‚ïó¬Ω¬ß√ÑN!‚ï¢‚îº‚ô´m√π}Jt‚Üív)‚ï¢+Œò‚òº√Æ‚ïî‚Üìb√â√º‚ï°‚åêC√á-‚ô†‚Ä¢¬ø‚ô™FM¬•2
```
[Run and debug it](https://staxlang.xyz/#p=86016ddb51bbab158e4e21b6c50e6d977d4a741a7629b62be90f8cc919629081b5a943802d0607a80d464d9d32&i=LBc4NtPY%7B%22%3E%3C%2B-.,%5B%5D%22XI%5Ei*%7D%2FzsFs%25Ntcaay%25%5E%28x_Iasn%40as%2B4NtPs%0AMove+the+pointer+to+the+right%0AMove+the+pointer+to+the+left%0AIncrement+the+memory+cell+at+the+pointer%0ADecrement+the+memory+cell+at+the+pointer%0AOutput+the+character+signified+by+the+cell+at+the+pointer%0AInput+a+character+and+store+it+in+the+cell+at+the+pointer%0AJump+past+the+matching+%5D+if+the+cell+at+the+pointer+is+0%0AJump+back+to+the+matching+%5B+if+the+cell+at+the+pointer+is+nonzero%0ANo+Operation)
Made this after Fmbalbuena's challenge in TNB. Will try to post something in Pip as well.
Found a nice save after Neil pointed out a mistake.
## Explanation
```
LBc4NtPY{"><+-.,[]"XI^i*}/zsFs%Ntcaay%^(x_Iasn@as+4NtPs
LBc4NtPY{"                                              No Operation
          >                                             Move the pointer to the right
           <                                            Move the pointer to the left
            +                                           Increment the memory cell at the pointer
             -                                          Decrement the memory cell at the pointer
              .                                         Output the character signified by the cell at the pointer
               ,                                        Input a character and store it in the cell at the pointer
                [                                       Jump past the matching ] if the cell at the pointer is 0
                 ]                                      Jump back to the matching [ if the cell at the pointer is nonzero
                  "XI^i*}/zsFs%Ntcaay%^(x_Iasn@as       No Operation
                                                 +      Increment the memory cell at the pointer
                                                  4NtPs No Operation
```
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), 46 bytes
```
¬Æ·π¨‚Ç¨z0a·∏∑≈º·πö‚Å∏·π≠·πö≈ª‚Ç¨4¬°o‚Å∂√∞‚Äú><+-.,[]‚Äùi‚±Æx·π†o≈íQ√Ñ¬©≈íQ∆≤$$·ªã≈ª‚Ç¨
```
[Try it online!](https://tio.run/##jdAxTwIxFAfw/T7FGxg0wIXBkTC5YKLE0RCGUh5clWsvvZ4RjAkYNzdHo4m6GBMgaoxyOSfI@T3aL3IeoIZBolNf37@/tH372G53kmQy0uHAnA66BaLHb/G7Di9Nf6zDYVrEURpsTG6F6b9OH03vqlTM5u1ctWZ618w8jY50eCPii93p2eQhXT6eMxkdnc9VoqMXPb6b3mf2kqRaK5aOT9bWs9l83rZzOWtbHCIoB8ETjCuUoMR8K1nLUSvTNjaVVeZUootczVsuukJ2gKZ/AaKWkbWJ/zxYCZQXLFrUIZLQ2ZU@a3HWZNiAemcR/SLLfAbJEiO8Ab4SEoEpYHyl3ApcDzzifz2OKOow3oIasOYqA8yHwgLWCT34HsqPrf5hueBdlMLaEVDxUBLFBP8E "Jelly ‚Äì Try It Online")
Program on the left and list of descriptions on the right. I suspect this can lose a few bytes fairly easily, but I'm posting it now in order to preserve one of the most hideous things I have ever written for posterity.
[Answer]
# [C (clang)](http://clang.llvm.org/), ~~191~~ 188 bytes
*-3 thanks to @[ceilingcat](https://codegolf.stackexchange.com/users/52904/ceilingcat)*
```
*S="><+-.,[]";i;l;d;f(char*a,**e){for(i=5,l=printf("    %s \n",a);*a;printf("%*s%s\n",l-i,"",e[d?d-(int)S:8]))for(d=index(S,*a),printf("%*c",i++,*a);!d&!index(S,*++a);)i+=write(1,a,*a>0);}
```
[Try it online!](https://tio.run/##lZJBb9QwEIXv/RVTS4vixFl1D0gIN8uFS5Gghz2GHFx7kh2R2JHjpS2r/euEeLctqSoo@OZ57316tkbnulW2Gcd0U7D1ZZYvRVkxSbKVRtaJ3iqfKpGmyPe18wkVb0Vb9J5sqBMG01kM8NUyobhMlXwUFumwGOK4zUkwJrA0H0yeTCLfvH9XcR5ZpiBr8C7ZiFRx8TuqmaAsi0N5bt6cP5mybJpwyopbTwGTlZh6qfUFl4exU2QTvj@LhY6VQTuDKyiAldXlen9IeJbl@XIpBJMzF971q7KabKdoPOyz@44Qtgi9mxqhh@COV0/NNjDxurHF@pnvymqPHdpwVDvsnL8HjW0LKszz88xH/P/M9S70u5MaX6d07DRQY6kmNHBzf5L@DrmykaFmBGUNDMF5BApA9l8gn3ZdD70aHtqroLdkG6iA6j/FgQa4eMG4Ufrb47c@YcpXMNbZH@jdHPbFwXWPXgVy9mF@OO3BtOJxU8RxFbg8O4w/dd2qZhjz218 "C (clang) ‚Äì Try It Online")
Assumes explanations are in the order `> < + - . , [ ] NOP`.
[Answer]
# [Perl 5](https://www.perl.org/) + `-nF -M5.10.0`, 93 bytes
Thanks to [@Fmbalbuena](https://codegolf.stackexchange.com/users/106959/fmbalbuena) for noticing I'd missed printing the unaltered string! Thanks to [@emanresu A](https://codegolf.stackexchange.com/users/100664/emanresu-a) and [@Neil](https://codegolf.stackexchange.com/users/17602/neil)'s regex wizardry saving 14 (!!) bytes!
```
@@=<>;say$"x4,$_,map$"x(4+$-).$_.$"x(@F-($-+=y///c)).$@[index'><+-.,[]',$_],/[^]<>+-.[
]+|./g
```
[Try it online!](https://tio.run/##K0gtyjH9/9/BwdbGzro4sVJFqcJERyVeJzexAMjUMNFW0dXUU4nXA3Ec3HQ1VHS1bSv19fWTNYHCDtGZeSmpFep2Ntq6ejrRsepAnbE6@tFxsTZ2QJForljtGj399P//IQr8/AOiY7l888tSIYRnXnJRam5qXgmXSyqMFRziAsbhGZk5qVASqI/rX35BSWZ@XvF/3Ty3/7q@pnqGBnoGCgA "Perl 5 ‚Äì Try It Online")
## Explanation
First `print` `4` `x` (string repetition operator) `$"` (which defaults to space), then store the length of the input (implicitly obtained via `-F` into `@F`) in `$=`, and store the explanations in `@@`. Then, `for` each matching piece of code (either one char from `-<>+.,[]`, or any number of any other chars) concatenate the following with `$\`: 4 + `$-` (which starts out as `0`) `x` `$"`, followed by the piece of code (`$_`), followed by the original length, minus `$-` (to which we add the current length of this code piece) `x` `$"` and finally, using the `index` function on the string `><+-.,[]`, the message associated to the current piece of code (`index` returns `-1` for missing index, for which Perl returns the last element of the list). `$_` is output followed by `$\` thanks to `-p` flag.
---
# [Perl 5](https://www.perl.org/) + `-F/([^]<>+-.[]+|.)/ -M5.10.0`, 92 bytes
The regex used in the above, can be provided via `-F` to save a byte.
```
$==y///c;@@=<>;say$"x4,$_,map/./&&$"x(4+$-).$_.$"x($=-($-+=y///c)).$@[index'><+-.,[]',$_],@F
```
[Try it online!](https://tio.run/##NYxLC4JAAITv/oxYfLAvAz35YA8idLCCgg7LJmILCb5QCYV@e9uWdZhhZuCbXg61rxSIooVSWgaMRWEcjMUCNrOHQI6aoqeEmqbutgcBdgjIyaeACNsAw5Vz9Mx41d7kbMUhxARxYWlcIJYqtS77w5ELI@secrVdWw6yke1kJPKfTufkq8u9quXPNWe8un6qunZUOKU2v4ow1o9cwCdxqMKZT7Yucd8 "Perl 5 ‚Äì Try It Online")
[Answer]
# [Ruby](https://www.ruby-lang.org/), 118 bytes
```
c,*a=*$<
print" "*l=4,c
c.scan(/[^+-.\[\]<>\n]+|./){puts" "*l+$&+" "*(c.size+4-l+=$&.size)+a["><+-.,[]".index($&)||8]}
```
[Try it online!](https://tio.run/##jdDNboJAEADgO08xIYSAC9iDhx7UUy82aX0ApMm6jrIpzJJlaIo/z04RW@Ohpr3t/Hw7s2ubddt1KhrJ2cibOpXVxC64o2I2iZSjklpJCsbpm4iTVbrKpvMVZeKYjMND1XA9dArPF@dD0HfrPYpJXIiZ5w9BKGTqzqe9jtLMTTRt8DPw/PB4fMxOXZf2Fx5OQShEHCdJFDkv5gOBc4TK9IugBTZDaPUu57vVArfsLEhZLJF4SJVYGtuCwqIAybfIecJ/Ni4b7h85pFQurVTnkbXekd5q3MC6vZR@kQs6Q3nDJG2gZmMRNIOmu/K5KSuoZP29nGSVa9pBBnp7z4Cu4eEC11K9/3zK1aZ/WDK0R2ucVwPLCq1kbegL "Ruby ‚Äì Try It Online")
#### Explanation
```
c,*a=*$<                                 # assign 'c' to first line and 'a' to the rest of input
print" "*l=4,c                           # output code and assign 'l' to 4 at the same time
c.scan(/[^+-.\[\]<>\n]+|./)              # for every match:
{puts" "*l+$&+" "*(c.size+4-l+=$&.size)+ # output the padded match, update 'l' to keep track of the spaces
a["><+-.,[]".index($&)||8]}              # output the correct explanation
```
inspiration taken from [lonelyelk](https://codegolf.stackexchange.com/users/108388/lonelyelk)
[Answer]
# [Haskell](https://www.haskell.org/), 330 bytes
```
import Data.List
main=interact$unlines.f.lines
f(c:a)=(s 4++c):(map(p c.(a%)).tail.inits.t)c
t r|r==[]=[]|q x=[x]:t y|0<1=a:t b where(x:y)=r;(a,b)=span(not.q)r
q=(`elem`n)
p c(a,e)=s(4+(l.init)a)++last a++s(1+length c-l a)++e
s=(`replicate`' ')
n="><+-.,[]"
e%j=(j,e!!(n#last j))
l=length.concat
(s:z)#c|[s]==c=0|z==[]=1|0<1=1+z#c
```
[Try it online!](https://tio.run/##jZJRbxoxDMff8yncsqqJDiKQ@sRIn/rSaVs/wOkkQmq40DvnSMwGjH12Fg5t6sPQJkVKYvvnf2yntukNm@Z08m0XIsOTZas/@8SitZ6MJ8ZoHX/YUuMJk17qfhdL6aZWGZngoSicmsrWdrIDp6W9U0qz9Y325DlpVk4wxGM0pqzyOm5gZ8pdNWXYH8ezibH5tIDvNUaUu@lemfhR2uFCmdRZkhRYb1QUGyPn2GA7JyWyTo7AHCEfCnkRUlYVRWMTgy2KJCdFg7TiGtyogbMLRcoZInaNd5Zxfg/3SpC5fZwVIz0sq1uBd2sj10O8uZE06DOtlRKNuSTSLlAGhUzTgxq4Y5kqY5wZHw99XZO@lElxGLjTqaxmjz9@yqw6Gmk9HIov4RsC1whd6DsKHPpr9Kuar3obXLJ4JhexReLe1GIb4h5cHhlYfg@JJ/zPwJctd9uLydX2PN0smfyK/NLjKyz2F9dfyGc6g/YdZukVEoeI4Bk8XSU/bdsOunNP@8dZdrWnFVTgl9cY8AnGF3Bh3dvvpvxhy3@wFOiAMYivAV66/InZB/oF "Haskell ‚Äì Try It Online")
#### Explanation:
```
import Data.List
main=interact$unlines.f.lines
f(c:a)=(s 4++c):(map(p c.(a%)).tail.inits.t)c
```
import Data.List `inits`(prefixes), this is used to keep track of the number of spaces  
call `f` with lines of input, then output each line  
f = `" " * 4 + code` +   
`map` on each `prefix` of each command or noop:  
select explanation and then pad with spaces  
```
t r|r==[]=[]|q x=[x]:t y|0<1=a:t b where(x:y)=r;(a,b)=span(not.q)r
q=(`elem`n)
n="><+-.,[]"
```
`t` splits the code into commands or noop  
`q` checks if a char is a command  
`n` is the string `"><+-.,[]"`
```
p c(a,e)=s(4+(l.init)a)++last a++s(1+length c-l a)++e
s=(`replicate`' ')
e%j=(j,e!!(n#last j))
(s:z)#c|[s]==c=0|z==[]=1|0<1=1+z#c
```
`p` pads a (prefix, explanation)-pair with spaces  
`s` returns n spaces  
`%` creates said (prefix, explanation)-pair  
`#` returns the index of the command in `n` or 8 if it's a noop
[Answer]
# [Vyxal 3](https://github.com/Vyxal/Vyxal/tree/version-3) `·π†`, ~~80~~ 79 bytes
```
D√∞4√ó¬ß,0$"<>+-.,[]"¬£([¬•nc[‚Å∞Lm-Íúù√∞√ó¬ß¬π,|n¬ß1#x)4m+√∞√ó¬ß¬•n·∏ûÍúù:[#?·∏¢in¬ß‚Å∞Lm-√∞√ó¬ß,0|n¬ß1][√∞¬ß¬π,
```
[Try it Online!](https://vyxal.github.io/latest.html#WyLhuaAiLCIiLCJEw7A0w5fCpywwJFwiPD4rLS4sW11cIsKjKFvCpW5jW+KBsExtLeqcncOww5fCp8K5LHxuwqcxI3gpNG0rw7DDl8KnwqVu4bie6pydOlsjP+G4omluwqfigbBMbS3DsMOXwqcsMHxuwqcxXVvDsMKnwrksIiwiIiwiKystLTw8Pj4uLiwsW1tdXWFhYmJjY34rKy0tPDwrKy0tPDw+Pi4uLCxbW11dYWFiYmNjfisrLS08PFxufmFhYWNcbjw8PDw8XG4+Pj4+PlxuKysrKytcbi0tLS0tXG4uLi4uLlxuLCwsLCxcbltbW1tbXG5dXV1dXSIsIjMuMy4wIl0=)
### Explanation:
Setup:
```
D√∞4√ó¬ß,0$"<>+-.,[]"¬£(¬≠‚Å°‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å£‚Äã‚Äé‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å£‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å§‚Äã‚Äé‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å§‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Å°‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å™‚Äè‚Å†‚Å™‚Å™‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Å¢‚Äã‚Äé‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå¬≠
 √∞4√ó¬ß                 ## ‚Äé‚Å°Print "    " without newline
D    ,                ## ‚Äé‚Å¢Print the first line of input with newline
        "<>+-.,[]"¬£   ## ‚Äé‚Å£Put "<>+-.,[]" in the register
      0$              ## ‚Äé‚Å¢‚Å°Push the 0 in the stack (Swapped because the top of the stack is used for looping)
                   (  ## ‚Äé‚Å§Loop every char in the first line of input
```
Looping part:
```
[¬•nc[‚Å∞Lm-Íúù√∞√ó¬ß¬π,|n¬ß1#x)4m+√∞√ó¬ß¬•n·∏ûÍúù:[#?·∏¢in¬ß‚Å∞Lm-√∞√ó¬ß,0|n¬ß1]¬≠‚Å°‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å™‚Äè‚Å†‚Å™‚Å™‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å£‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å£‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å¢‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å§‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å¢‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å£‚Å§‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Å°‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å§‚Å§‚Å™‚Äè‚Å†‚Å™‚Å™‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Å¢‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å¢‚Å™‚Äè‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Å£‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å°‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å¢‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å£‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å§‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å°‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Å§‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å£‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å°‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å¢‚Å°‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å¢‚Å¢‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå¬≠
[¬•nc[                                                   ## ‚Äé‚Å°if the current character is in "<>+-.,[]"
     ‚Å∞Lm-Íúù√∞√ó¬ß¬π,                                         ## ‚Äé‚Å¢print that many spaces, then the second line of input, with newline.
               |n¬ß1#x)                                  ## ‚Äé‚Å£else print the current character and continue with the 1 in the top of the stack.
                      4m+√∞√ó¬ß                            ## ‚Äé‚Å§Print that many spaces
                            ¬•n·∏ûÍúù                        ## ‚Äé‚Å¢‚Å°index of the current character (1 to 8, 0 if not found)
                                :[                      ## ‚Äé‚Å¢‚Å¢if the index of the current character is 1 or more
                                  #?·∏¢in¬ß‚Å∞Lm-√∞√ó¬ß,0       ## ‚Äé‚Å¢‚Å£Print that many spaces, then the right explanation, with newline, and push 0
                                                 |n¬ß1]  ## ‚Äé‚Å¢‚Å§else, print the current character, and push 1
```
Final part:
```
[√∞¬ß¬π,¬≠‚Å°‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å°‚Å™‚Äè‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å¢‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å°‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å£‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å£‚Å™‚Äè‚Å†‚Å™‚Å™‚Å†‚Å™‚Å™‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå‚Å§‚Äã‚Äé‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å§‚Å™‚Äè‚Å†‚Äé‚Å™‚Å°‚Å™‚Å†‚Å™‚Å¢‚Å°‚Å™‚Äè‚Äè‚Äã‚Å°‚Å†‚Å°‚Äå¬≠
[      ## ‚Äé‚Å°If the top of stack is 1 or greater
       ## ‚Äé‚Å¢(I have no idea why that works)
 √∞¬ß    ## ‚Äé‚Å£print " " without newline
   ¬π,  ## ‚Äé‚Å§Print the second line of input, with newline
üíé
```
Created with the help of [Luminespire](https://vyxal.github.io/Luminespire).
[Answer]
# [Retina](https://github.com/m-ender/retina/wiki/The-Language), ~~207~~ 205 bytes
```
*\K````
*\0G`
\G.
$& $&¬∂
m,-10T`_><+\-.,[]p`d`.$
(?<=^(.+¬∂)*.) 9¬∂(?=. 9)
+`^(.+¬∂)*(.)+ .¬∂(?!¬∂|(?<-2> )*(?(2)$))
$& 
,-10P`.+
+`(\d)( *)(¬∂(.+¬∂)*¬∂)
$2$1*_$3
+`(_)+(¬∂(.+¬∂)*(?<-1>.*¬∂)+(.*))
$4$2
(¬∂.*){9}$
```
```
[Try it online!](https://tio.run/##RU/NagIxEL7PU6QQZCZxB3ftZUF3L4KU0lao4MHYjWhAQbdFpJe2r7UPsC@2nVSlgW@Y5PuZySmc9/U67TrjHr0cMG4w9eCmDLqndK9t4NhP0sHcV8XIuoT7y9WH33rWgOVo/IZs24YMk8rbBssxq5wArL8RyGQVR@qubb7FkmSFkucSM9JEcQjE/JlnKzZ0W0JlCMVxCRCAznRqKj2MgorsPxnz0oKjyCKbmHevMxCBXL7yHw3ypa6TzWXx55fZcgVP75/hUh7qzSkcQ32GSbh1r/PJHxa7/SFcq/h@AQ "Retina ‚Äì Try It Online") Explanation:
```
*\K````
```
Output the leading fence.
```
*\0G`
```
Output the line of code.
```
\G.
$& $&¬∂
```
Split the line of code into characters. For each character, repeat it twice, joined with a space.
```
m,-10T`_><+\-.,[]p`d`.$
```
Transliterate the last character of each pair to a digit `1-8`, with unknown characters becoming `9`.
```
(?<=^(.+¬∂)*.) 9¬∂(?=. 9)
```
Join together all runs of unknown characters.
```
+`^(.+¬∂)*(.)+ .¬∂(?!¬∂|(?<-2> )*(?(2)$))
$& 
```
(note trailing space) Align each run after the end of the previous run.
```
,-10P`.+
```
Pad all of the explanation lines to the same width.
```
+`(\d)( *)(¬∂(.+¬∂)*¬∂)
$2$1*_$3
```
Convert all of the transliterated digits to runs of underscores and move them to the end of the line.
```
+`(_)+(¬∂(.+¬∂)*(?<-1>.*¬∂)+(.*))
$4$2
```
Replace each run of underscores with the appropriate line of explanation.
```
(¬∂.*){9}$
```
```
Replace all of the explanations with the trailing fence.
[Answer]
# [Ruby](https://www.ruby-lang.org/), ~~143~~ ~~142~~ 138 bytes
```
->i{c,*e=i.split ?\n;puts" "*(m=4)+c;c.scan(/[^<>+-.,\[\]]+|./){|b|r=" ".*c.size+5;r[m,z=b.size]=b;puts r+e["<>+-.,[]".index(b)||8];m+=z}}
```
[Try it online!](https://tio.run/##7ZOxTsMwEIb3PMWpU1snLlQgITUJC0uRaBlgco3kuNfWIrEjx0W0SZ69hARQByoYGfDku/u/89m/bLfJ7pBGhyBWpfSHGCla5KlycL3Qk3zrih70hv0suhgQOZG0kEL3R@wpjElA/QVbcE4qOhqUVVLZqNHSYSNSeySXE8syfx8lbcijpO0GliDrdTTjPar0El/7yaCqrvgkI9G@rg9KN8pziCAMp7P7xweP8TAu6/6AkCCg1Pe9O/OC4DYIuVHaoQVn2tCq9cadrKa4ct5US4sZatemMsyM3YHENAXhjiHvBn8pnG9dM2@bkhthhXw/slBrrVYKl5DsutI35PT9oiCOMKGXUDhjERoHlD5J3m6zHHJRfAwnnNwovQYOanWKAVXAWQcmQj5/PsoXy35gtdF7tMabGZjnaIVTRnudP61h4yPDYtIuVpahT@Ogrvm/ZX/LMi9l3Tfjn7sxP7wB "Ruby ‚Äì Try It Online")
The function expects input to be lines separated by `\n`. It scans the program using regexp `/[^<>+\.,\[\]-]+|./`. It outputs to stdout instead of returning. Which is all there is to it.
Thanks to @Fmbalbuena for removing a space!
Saved 4 more bytes by re-reading ruby golfing tips :)
[Answer]
# [Haskell](https://www.haskell.org/), 235 231 bytes
```
import Data.List
main=interact$unlines.map("    "++).f"><+-.,[]".lines
f o(i:e)|let t=not.(`elem`o);p=(>>" ").concat;w((c:r):t)=(c:r++p t++' ':maybe(e!!8)id(lookup c$zip o e)):[p[c:r]++l|l<-w t];w[]=[]=i:w(groupBy(\x y->t x&&t y)i)
```
[Try it online!](https://tio.run/##jZLPbtswDMbvfgrWKFoJio0dByf2Yeilw7Y@gGegikLHRPQPNr3UXffsmZNsQw8LWoIHip9@oPhBnR52aO3hQC6GnuFOs86/0MCJ0@RL8oy9Nnw9ekseh9zpKFKYI1VK5m1arVSWL@omzU960kIQVKB8scjApQ@ci0e06B6DXMZSVFUKqcxN8Ebzci@EKXpZsCyPhVIRWKlbuC2cntYo8Orqo6SNsCHsxgjm@pkiBEApizrWM9EoZV/sKtsDN8t93ZRzUrEX2z6M8dMkvj/BlFUMTzc3DJMkeTjUzar6@UtIpbIszxeL5Gv4gcAdQgyndYHD6djTtuOLqsWWk3tvenTo@dRy6EI/gZn9BM2voeQO33nxYeQ4nlum00fr55EDbT21hBtYT2fpP@S9P4L6Fab9BgYOPQIxkL9Ifh5dhKiHP4/TbDryW2iA2ksM0AAfzuBam91fU/6x9RusD/4Z@5B8C/AQ5x/GFPxv "Haskell ‚Äì Try It Online")
Old answer:
**[Haskell](https://www.haskell.org/), 235 bytes**
```
import Data.List
main=interact$unlines.map("    "++).f.lines
o="><+-.,[]"
t=not.(`elem`o)
p=(>>" ").concat
f(i:e)|let w((c:r):t)=(c:r++p t++' ':maybe(last e)id(lookup c$zip o e)):[p[c:r]++l|l<-w t];w[]=[]=i:(w$groupBy(\x y->t x&&t y)i)
```
[Try it online!](https://tio.run/##jZLBbtswDIbvegrCCFoJio2dvdiHopcW2/oAnoEqCh0TkSXBppe66549cxx06GHBRuhA/tQHUj/UmuGAzp1O1MXQM9wbNtkXGlh0hnxBnrE3llejd@RxyDoTZQJzJFqrrMkWVYQiKTc6zdZVnQgufOBMPqPD7jkoEQtZlgkkKrPBW8OikZSjenPIcJTS5r3KWRXnROsIrPUt3OadmbYonRkYUNFOuhAOYwS7eqUIYdZUXsVqZmqt3ZvbpEfg@vOxqov5UC6Pq30fxng3ye8vMKUlw8vNDcOkSJ1OVb0pf/6SSus0zbL1WnwNPxC4RYhheTJwWMqe9i1f7TpsWDx422OHnhepwy70E9jZUzD8ERL3@J8Xn0aO40WyrTnbP48caO@pIdzBdrq0/kI@@DNoPmDG72Dg0CMQA/mr5OPYRYhnt5flDNuW/B5qoOYaAzTApwu4NfbwbsoftvoH64N/xT6IbwGe4vzLmIL/DQ "Haskell ‚Äì Try It Online")
*The answer is not final, will probably be golfed further.*
]