One of the most important skills to learn when you’re programming is learning how to break your scripts. You’ll want to do lots of tests with lots of different kinds of data, but tests can only find errors that you test on. You will also need to think about where will this break? and fix those errors before they happen. We’ve done a little of this already, without calling it that. This is why we put “open(…)” in an “if” statement and match it with an “else” that displays any errors that crop up.
It is especially important to think about how new functionality can break your script. So we recently added the ability to search, sort, and export by new fields. We can add any field we want to @validFields and search, sort, and export by that field. How can that break our script?
One way it could break our script is if we try to export on that field but the song doesn’t have anything entered for it.
In fact, that might be the case even with our current fields. How can we find fields that don’t have anything in them?
We’re doing our search by regular expression. We haven’t blocked regular expression characters from the search text. Try:
./show --artist ^Night songs.txt
./show --artist Night$ songs.txt
The first one will show only those songs by artists whose name begins with “night”. The second shows artists whose names end with “night”. Because that’s the regular expression character for anchoring to the beginning or end of a text.
There’s also a regular expression for any character. If we search on that, and then get the reverse, we can find fields that have no character in them.
./show --artist . --reverse songs.txt
./show --song . --reverse songs.txt
./show --album . --reverse songs.txt
./show --genre . --reverse songs.txt
There are artists, albums, and genres that are completely empty. Try to export on artist and you’ll get an error:
./show --artist . --reverse --export artist songs.txt
Unable to open : No such file or directory
There’s no way to open a file that has no name. We need to check for empty filenames and give them some other name, such as “Unknown artist”.
In the “if ($exportField) area that we just changed, change it again:
if ($exportField) {
$filename = $$exportField;
if ($filename ne "") {
$filename = replace($filename, "/", "-");
} else {
$filename = "Unknown $exportField";
}
$matches[$#matches]{'file'} = $filename;
}
Now, if $filename ends up being not equal to an empty string, we do the replace as normal. Otherwise, we assign “Unknown $exportField” to $filename. If we are exporting by artist, it will say “Unknown artist”.
The “if ($filename ne "") {” is a little different from “if ($filename = $$exportField) {” which we could have done. The former will only match if $filename is empty. The latter would also match if $filename was zero. We might imagine wanting to export based on rating, so that we have a list of songs each in a file named after their rating. A rating of zero would get a filename of “Unknown rating” if we used the latter form, but will get a filename of “0” with the one we used.