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
Direct Download
Read full article as PDF:
Price $2.95
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Find SysAdmin Jobs
News
-
Kubuntu Focus Announces XE Gen 2 Linux Laptop
Another Kubuntu-based laptop has arrived to be your next ultra-portable powerhouse with a Linux heart.
-
MNT Seeks Financial Backing for New Seven-Inch Linux Laptop
MNT Pocket Reform is a tiny laptop that is modular, upgradable, recyclable, reusable, and ships with Debian Linux.
-
Ubuntu Flatpak Remix Adds Flatpak Support Preinstalled
If you're looking for a version of Ubuntu that includes Flatpak support out of the box, there's one clear option.
-
Gnome 44 Release Candidate Now Available
The Gnome 44 release candidate has officially arrived and adds a few changes into the mix.
-
Flathub Vying to Become the Standard Linux App Store
If the Flathub team has any say in the matter, their product will become the default tool for installing Linux apps in 2023.
-
Debian 12 to Ship with KDE Plasma 5.27
The Debian development team has shifted to the latest version of KDE for their testing branch.
-
Planet Computers Launches ARM-based Linux Desktop PCs
The firm that originally released a line of mobile keyboards has taken a different direction and has developed a new line of out-of-the-box mini Linux desktop computers.
-
Ubuntu No Longer Shipping with Flatpak
In a move that probably won’t come as a shock to many, Ubuntu and all of its official spins will no longer ship with Flatpak installed.
-
openSUSE Leap 15.5 Beta Now Available
The final version of the Leap 15 series of openSUSE is available for beta testing and offers only new software versions.
-
Linux Kernel 6.2 Released with New Hardware Support
Find out what's new in the most recent release from Linus Torvalds and the Linux kernel team.