The code in line with text is from surrounding it with backticks (the ` which is under the ~ on at least US keyboards) ā it looks like youāve figured out the four-spaces-at-the-front for doing the entire line, which automatically joins multiple lines into larger blocks. Howād you get the colors on yours, though? Thatās something I donāt know. And sorry about the two dashes; I meant for them to just be an en-dash separating the second part of the sentence.
Not sure why the Compilations folder has disappeared ā that (with no āsā) was actually what most of my tests wound up being sorted with ā but the second soundtrack looks like it might be due to the album artist having been overridden; itās in the same āslotā as the artists for the other release types. Do both artist fields show up correctly in the bottom pane of Picard?
EDIT: Thereās a chance that has something to do with MagicScript, since it doesnāt include artists in the soundtrack hierarchy, but it doesnāt save anything over the tags so unless you have something in your file namer that doesnāt show up in your original post, Iām not sure why it would affect anything
And definitely happy to explain it! One resource Iāve found invaluable, if you havenāt seen it already, is the scripting documentation page. Not necessarily a fun read, but itās really nice to take twenty minutes and just figure out everything thatās possible.
$if2(%_secondaryreleasetype%,studio)
%_secondaryreleasetype%
unsurprisingly contains a list of all the secondary types on the release group, in lowercase. You can find a list of everything you can use on the tags page, but my favorite way of finding something helpful is using the āView script variablesā plugin. Anyway, when this list variableās used normally (as in, not through one of the $...multi
functions), the types are separated by a semicolon and a space; this will come into play later. For now, all we care about is if the release group has any of them set, so we use an $if2(...)
to select the entire list if itās not empty, or the text āstudioā if it is. The function can take pretty much as many comma-separated arguments as you want to give it, and returns the first one thatās not empty.
$upper($firstalphachar([...]))
From that result, take only the first character and turn it into uppercase. This would normally cause unexpected behaviour if the first character wasnāt a letter, but since none of the secondary types use anything but letters in their name, we donāt have to worry about it. As a note, the first āAlbumsā you added to your line (and, in fact, everything after the s
) doesnāt do anything because $firstalphachar
drops it. Thatās also why I had studio
in all lowercase ā itās automatically capitalized, so if I match whatās in %_secondaryreleasetype
, itās less likely to do anything weird if I edit the script in the future.
$rreplace([...],.\([^;]*\).*,\ā\1)/
(Donāt copy that, thereās a zero-width space between the two backslashes.) This, admittedly, looks a bit like magic. $rreplace([...])
runs a regex on some text, and those are rather infamously difficult to read. It isnāt helped at all by the fact that Picard parses the script before the regex is run, so thereās more backslashes in there than normal (for a digression on this, check out this page and look for sections talking about the title text). At a high level, the expression between the commas is matched to parts of the text before the first comma, and those matches are replaced with the value after the second comma. To take it an element at a time:
-
.
- This matches any single character. Since regexes are greedy (matching at the first possible point and not going to the next part of the expression until they have to), this will always be the first character in the string, If we were using something else or wanted to be particularly careful, we would put a ^
at the beginning of the expression, which only matches the beginning of the string. The .
is in here because we already have the first character from the $upper([...])
expression.
-
\(
- Iāll explain this later, but itās escaped (the backslash) because a plain (
has a special meaning in the script that we donāt want to invoke.
-
[^;]
- Square brackets usually mean āmatch any of these charactersā, but the ^
being right after the [
makes it āmatch everything except these charactersā (as opposed to what ^
means at the start of a regex). Therefore, this matches any (single) character thatās not a semicolon ā what separates the elements of the list, remember.
-
*
- This takes the last element (in this case, the [^;]
) and matches it any number of times, zero to theoretical infinity. Again, regexes are greedy, so if we want it to stop at some point before the end of the line, we have to tell it when to stop before the *
: in this case, when it hits the first semicolon (if thereās no semicolon in the string, it just takes everything until the end of the input). This will then be āthe first element of the list, ignoring the first characterā since that was already matched.
-
\)
- Again, escaped due to having another meaning; the pair would typically be read ([^;]*)
. Doesnāt match anything on its own, but saves everything between the parentheses into memory to be referred back to later.
-
.*
- I assume youāve been paying attention and can figure this out from the above, but for completeness, match any number of any character; basically, āmatch the entire rest of the lineā. Like with ^
, if we werenāt using such a broad wildcard or we wanted to be careful, we could add a $
to the end to be sure we match the end of the line, but itās not necessary after .*
.
-
\ā\1
- (Like above, retype this, donāt copy it.) This is how we retrieve the value saved by (
and )
ā or, more generally, \1
, but the backslash also needs to be escaped here. Since this is after the second comma, weāve switched from matching text to replacing whatever was matched. Because we made sure to get the entire line, this takes whatever we gave as input and replaces it with the first saved group, essentially discarding the first character, the first semicolon, and everything after that.
$rreplace([ā¦]) Albums/
If I may make another suggestion, this is what Iād do to add the āAlbumsā part of the name, as long as you donāt mind āCompilation Albumsā and āSoundtrack Albumsā. You get it applied across the board, and donāt run into āStudio Albumsā behaving differently than everything else. If you do want folders without the second word, you can always do something like $if($ne($left(%_secondaryreleasetype%,10),soundtrack), Albums,)
to only add it if the first 10 characters of the first release type in the list donāt match āsoundtrackā (or, more correctly, to add an empty string if they do), and if youāre being lazy, you can even replace 10
with $len(soundtrack)
to do the counting for you.