A Go program displays song lyrics line by line
Music in YAML
The songFinder()
function in Listing 3 is used to find YAML files with lyrics. Go supports the conversion of YAML data into Go structures as a built-in feature. It only requires the programmer to decorate Go structures, such as Lyrics
from line 12, with instructions on the YAML format if the keys in the YAML text differ from the Go structure's attribute names.
Starting in line 12, Lyrics
stipulates in reverse quotes that keys in YAML conventionally start with lowercase letters, while publicly accessible fields in Go structures are uppercase. For example, the first line of the Lyrics
structure uses
Song string `yaml: "song"`
to stipulate that the Song
field is of the type string
, but is now named song
in YAML instead of Song
.
With this decoration, the Unmarshal()
function in line 46 effortlessly converts the YAML data into the internal format of the Lyrics struct
, without the programmer having to do anything else.
This only leaves the songFinder()
to call filepath.Walk()
and walk through all the .yaml
files (or .yml
, as matched by the regular expression) below the given directory, call parseSongFile()
for each file found, and feed the data below the artist/title key to the lyrics
map in line 33.
The songFinder()
function returns the result as a variable and, in line with the Go convention, an error code set to nil
if everything worked as planned, and if not, for the main program to take a closer look at what happened.
Event-Driven Actions
Managing the terminal UI, which consists of two superimposed list boxes of the same size, justifies a separate function handleUI()
in Listing 4. To determine which list box is on top and therefore visible, the function updates the inFocus
variable, setting it either to the main menu (lb
) or the text window (ltext
) list box.
As is the wont of graphical user interfaces, line 19 triggers an infinite loop whose only action is a select
statement. It receives events from the uiEvents
channel, sent out by the termui library for business logic to consume. For example, if the user presses Q, an event whose ID
field is set to q
is propelled through the channel. The case
handler in line 23 then triggers a return
, which terminates handleUI()
and accordingly the calling main program.
Actions related to arrow keys only matter if inFocus
indicates that the main menu is active. In this case, lines 27 and 32 call the ScrollDown()
and ScrollUp()
list box widget's functions. This is followed by the ui.Render(lb)
command, which redraws the widget. This is critically important, because otherwise the user wouldn't visually notice the change.
If the channel uiEvents
returns an event for the Enter key, the further processing depends on which mode is currently active. If the user is in the main menu, inFocus
is set to lb
, and line 37 uses the numerical index of the selected list box entry to retrieve its text representation (i.e., the artist and title) from the list box.
The if
block then sets the inFocus
variable to ltext
, activating the lyrics window in the process. A scanner, newly defined in line 41, grabs the text string with the lyrics lines from the lyrics structure and returns the next string line each time its Scan()
method is called. The switch from the main menu to the lyrics mode is initiated by line 39. This is also visualized for the user as soon as the lyrics list box is passed to ui.Render()
.
When the user presses Enter in lyrics mode, the if
block starting in line 45 is used. The text scanner retrieves the next line of the song from the multiple-line string in the YAML data starting in line 47; it discards any blank lines and appends newly read lines to the array slice of the ltext
list box. ScrollDown()
marks the new line in the display as the selected element and highlights its text in red. Again, the whole thing is only visualized after calling ui.Render()
.
If the song ends (i.e., the scanner fails to deliver any further lines), the if
block deletes the text lines from the ltext
listbox starting in line 58 and then switches back to main menu mode by pointing inFocus
at lb
. The same thing happens if the user presses Esc; in this case, the case
block switches to the main menu starting in line 64.
Quickly Built
To create the lyrics
binary file, which controls the tool from A to Z, you simply compile all three listings, as shown in Listing 5. The initial call to go mod
initializes a new Go module that tells the following go build
to fetch all the required packages from GitHub and include these as well.
Listing 5
Generating a Binary
$ go mod init lyrics $ go build lyrics.go find.go uihandler.go
After the successful build, make sure to fill your data
directory with a few song lyrics in YAML format, then call lyrics
, and remember, sing only at moderate volume to be considerate of your neighbors!
« Previous 1 2
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you've found an article to be beneficial.
News
-
PipeWire 1.0 Officially Released
PipeWire was created to take the place of the oft-troubled PulseAudio and has finally reached the 1.0 status as a major update with plenty of improvements and the usual bug fixes.
-
Rocky Linux 9.3 Available for Download
The latest version of the RHEL alternative is now available and brings back cloud and container images for ppc64le along with plenty of new features and fixes.
-
Ubuntu Budgie Shifts How to Tackle Wayland
Ubuntu Budgie has yet to make the switch to Wayland but with a change in approaches, they're finally on track to making it happen.
-
TUXEDO's New Ultraportable Linux Workstation Released
The TUXEDO Pulse 14 blends portability with power, thanks to the AMD Ryzen 7 7840HS CPU.
-
AlmaLinux Will No Longer Be "Just Another RHEL Clone"
With the release of AlmaLinux 9.3, the distribution will be built entirely from upstream sources.
-
elementary OS 8 Has a Big Surprise in Store
When elementary OS 8 finally arrives, it will not only be based on Ubuntu 24.04 but it will also default to Wayland for better performance and security.
-
OpenELA Releases Enterprise Linux Source Code
With Red Hat restricting the source for RHEL, it was only a matter of time before those who depended on that source struck out on their own.
-
StripedFly Malware Hiding in Plain Sight as a Cryptocurrency Miner
A rather deceptive piece of malware has infected 1 million Windows and Linux hosts since 2017.
-
Experimental Wayland Support Planned for Linux Mint 21.3
As with most Linux distributions, the migration to Wayland is in full force. While some distributions have already made the move, Linux Mint has been a bit slower to do so.
-
Window Maker Live 0.96.0-0 Released
If you're a fan of the Window Maker window manager, there's a new official release of the Linux distribution that champions the old-school user interface.