Got it working! Thanks for that AI suggestion @bernhard it did a lot of the leg work for me, and thanks @diogo for your suggestion as well, though it is easier to read and write the standard format with the chords above the lyrics. While there is software that will do the parsing to the chords within the lyrics for me (there's one called ChordPro) I was trying to remove the "middle man" so to speak and be able to edit and create lyrics directly and easily in ProcessWire. If anyone else is interested below is the code which creates an array with all the columns, sections and lines
$started_chords = false;
$chord_line = "";
$lyric = [[]];
$column = 0;
$section = -1;
foreach (explode("\n", $page->psalm_lyrics) as $line) {
$stripped = preg_replace('/\s+/', ' ', trim($line));
if ($stripped) {
if (array_key_exists($stripped, $sections)) { // START SECTION
$section++;
$lyric[$column][] = [
"class" => $sections[$stripped],
"lines" => []
];
} elseif (empty(array_diff(explode(" ", $stripped), $chords)) && !$started_chords) {
$started_chords = true;
$chord_line = $line;
} elseif ($stripped === "---") {
$lyric[] = [];
$column++;
$section = -1;
} else {
if ($started_chords) {
$started_chords = false;
$chord_line = rtrim($chord_line);
$limit = 0;
while ($chord_line && $limit < 10) {
$i = strrpos($chord_line, " ") ? strrpos($chord_line, " ") + 1 : 0;
$stripped = mb_substr($stripped, 0, $i, 'UTF-8') .
"<span class='chord'>" . mb_substr($chord_line, $i, null, 'UTF-8') . "</span>" .
mb_substr($stripped, $i, null, 'UTF-8');
$chord_line = rtrim(mb_substr($chord_line, 0, $i, 'UTF-8'));
$limit++;
}
}
$lyric[$column][$section]["lines"][] = $stripped;
}
}
}
Where $sections is a ProcessWire repeater field that parses different starts of sections like [VERSE] and [CHORUS] and then translates those to a class, and $chords is an array of available chords to parse. I can then write out the lyric wherever I need it.
<div class="lyrics mt-md">
<?php foreach($lyric as $c) {
echo "<div class='column'>";
foreach($c as $s) {
echo "<div class='section " . $s['class'] . "'>";
foreach($s["lines"] as $l) {
echo "<p class='line'>$l</p>";
}
echo "</div>";
}
echo "</div>";
} ?>
</div>
So this lyric for example:
[CHORUS]
E D G B
I'll take you for a ride
E D G B
On my garbage truck
B A
Oh no
---
[VERSE]
E D G B
I'll take you to the dump
E D G B
'Cuz you're my queen
A C
Take you uptown
A C
I'll show you the sights
C D
You know you wanna ride
Will render like this