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
-
Canonical Releases Ubuntu 24.04
After a brief pause because of the XZ vulnerability, Ubuntu 24.04 is now available for install.
-
Linux Servers Targeted by Akira Ransomware
A group of bad actors who have already extorted $42 million have their sights set on the Linux platform.
-
TUXEDO Computers Unveils Linux Laptop Featuring AMD Ryzen CPU
This latest release is the first laptop to include the new CPU from Ryzen and Linux preinstalled.
-
XZ Gets the All-Clear
The back door xz vulnerability has been officially reverted for Fedora 40 and versions 38 and 39 were never affected.
-
Canonical Collaborates with Qualcomm on New Venture
This new joint effort is geared toward bringing Ubuntu and Ubuntu Core to Qualcomm-powered devices.
-
Kodi 21.0 Open-Source Entertainment Hub Released
After a year of development, the award-winning Kodi cross-platform, media center software is now available with many new additions and improvements.
-
Linux Usage Increases in Two Key Areas
If market share is your thing, you'll be happy to know that Linux is on the rise in two areas that, if they keep climbing, could have serious meaning for Linux's future.
-
Vulnerability Discovered in xz Libraries
An urgent alert for Fedora 40 has been posted and users should pay attention.
-
Canonical Bumps LTS Support to 12 years
If you're worried that your Ubuntu LTS release won't be supported long enough to last, Canonical has a surprise for you in the form of 12 years of security coverage.
-
Fedora 40 Beta Released Soon
With the official release of Fedora 40 coming in April, it's almost time to download the beta and see what's new.