 In the last couple of days, I've spent several hours playing around with some scripting and in particular I've been scripting using a program called Whiptail. Whiptail is essentially a smaller, more minimal kind of alternative to the old dialogue program. You guys probably know dialogue, which is an in-curses, a text-based kind of widget program that allows you to have kind of dialogue boxes and menu systems and things like that. For example, if you were doing a Linux installation at a TTY, a lot of those old school in-curses installers used programs such as Dialogue, or in my case, Whiptail. Whiptail doesn't use the in-curses library, though Whiptail actually uses the Newt Programming Library, which is very similar, if I can actually show you some of Newt here, I don't know if this is a Whiptail box, it probably is, but you can see it looks pretty much the same as Dialogue. You couldn't tell the difference between Dialogue and Whiptail. The one thing with using Whiptail versus Dialogue, Dialogue is a much more complicated program. There's a lot more options, there's a lot more functionality built into it, which could be good for some users. For me, I found it a little complicated. I didn't like working with it. I used Dialogue a little bit in my DTOS installation script, but I've been looking to swap out Dialogue for something else, which is why I've been trying out Whiptail. When I found Whiptail to be pretty easy to use, there's a couple of peculiarities with Whiptail. If I go to this page here, Bash Shell Scripting with Whiptail, I pretty much based everything I did off of this page. This page is great. It gives you examples of various Whiptail boxes. That's an example, Dialogue box, yes or no, OK cancel. This is just a message that all it has is the one button, OK. Here is you entering a password. Here is a list of items to choose from. There is a checklist and there is a radio list. So, you know, you can pretty much do anything you want to do with Whiptail. One oddity to Whiptail, if I switch over to Emacs here, this is the script I've been working on really as an example, but it may eventually, this code may make its way into DTOS, the DTOS installation script. One oddity with Whiptail is you have no way, if I scroll down to the Whiptail code, this is basically creating the Whiptail box, the window that would appear. One of the strange things about Whiptail compared to Dialogue, Dialogue, you could choose coloring and bold text and italics and all of that stuff. You could actually place that inside, for example, the dash dash title flag, you know, and I'd have some string that would be the title of the window, but you know, I could do backslash capital Z and then some color, I think one through seven or zero through seven, it's the first eight colors of your 16 base color scheme, your X resources color scheme, or whatever color scheme your terminal is using, so I could do slash Z1 to color it with the one color, right, or the two color, or whatever, you know, or I could do backslash Z, slower case B, I think, for bold or whatever, you know, you can't do any of that in Whiptail. Whiptail doesn't take that stuff, it has no functionality for you to specify colors in the windows themselves. What you actually have to do, and I actually found this over on Ask Ubuntu, I made a note where I found the thread on Ask Ubuntu, how do you color, how do you specify specific colors with these Whiptail boxes? And you do it through exports, you have to export Newt, again, Newt is the widget library right there, basically, incurses type library, Newt underscore colors, and then you export these various variables for root, window, shadow, border, title, there's probably twice as many variables as this available, three times as many, these were just some of the ones that I found that I wanted to specify here. But before we dive too deeply into the code, let me just show you the script in action, so I'm going to CD into the directory where I have the script, and I'm just going to execute it, and it's pretty self-explanatory what I'm doing here in this Whiptail window here, I've created a checklist. So what this is, imagine this is part of DTOS, it's not part of the DTOS script yet, but it may make its way there. And right now I've got this screen, the title is web browsers, and select one or more web browsers to install, and you'll notice I've got a list of about 12 different web browsers that are available for installation on Arch and Arch Linux-based systems. Some of these are proprietary software, most of them are free and open source software, but I included some popular proprietary browsers, because I know, for example, a lot of people are going to want to install Google Chrome, for example, I get it. Now you'll notice that some of these web browsers, I've got four of them that actually are marked with a asterisk, it's because those four web browsers are already installed on my system. I've included some code in the script where it checks to see if the binary for all of these exist on my system. And the ones that it does find on my system, I've told it to turn the checkbox on, meaning mark it with a asterisk, that way I know I don't have to install Brave, for example, because it's already marked. I already know it's installed on the system. And this is important for DTOS because DTOS is able to be installed on any Arch Linux-based distribution. So a lot of times you're installing DTOS on, you know, Manjaro or Arco or whatever it happens to be. What programs are already installed out of the box? Well, unless you've been using that distribution for a while, you may not know. And this way, it'll let you know, I don't have to install Firefox, Firefox is already installed. Now let me hit tab twice. So if I tab, I get to the okay button. And if I hit okay, it would try to install these. I guess I could go ahead and hit the okay button. All it's gonna do, it's gonna ask me for my sudo password because it's running a Pac-Man install, everything that had a asterisk. And then nothing happened because the four programs that were marked were the ones I already had installed. So it didn't need to install anything. If I just wanted to bypass that all together, maybe I didn't want to install any of these. I could hit tab a couple of times and get to cancel. By the way, the next screen is the other internet program. So first screen was web browsers. This is other internet stuff such as telegram, transmission element files, Zilla Discord, Thunderbird, yada, yada, yada. I'll hit cancel, then we get to the next screen. Multimedia programs. I have another list of about 12 things. Most of them are already marked because most of them I already have installed. Let me tab down to cancel. And then the next screen is office programs. And then finally, I have a screen of mostly free and open source games. And I've also have a Steam and Lutrus as a part of the list as well. Let me cancel that. So that is really all this script is. So let me briefly walk you through this script because the way I've got it, it is a little complicated to read because I've got some things out of order with the way these functions are laid out. I'm actually gonna scroll all the way to the bottom. So my whippetail box has five screens, right? It was browsers, other internet, multimedia, office, and games. You see I'm just running these five functions at the end of the script. Now I've defined all of these five functions earlier in the script. So if I just scroll back, this is the games function. Right here. And what this is, I've defined a title. That's the window title. The title of that whippetail box, remember, was games. And then the text is there were three lines of text up under the title. Let me turn off truncated lines here. The three lines are gaming programs available for installation, new line. All programs marked with asterisks are installed already. New line, unselecting them will not uninstall them. Just letting you know, unselecting anything that's already been installed will not uninstall it from the whippetail box. Or at least right now, the way the script is designed, I don't have that functionality built in, but so I've got the title and the text to find these variables that I'll use later when I create the whippetail box. And then I create this local array. And this local array is nice because I have two different values. I can assign it, and this is very important. I actually assign the first value, which is called the key. These are the names of the actual program that Pacman installs. So this is the package name. And then the value, the second value here is what this is, is the executable binary that you would run if the program is installed. Because remember, I'm gonna run a check to see if this is installed. For example, if I install the game Sauerbrotten, that's the package. But when I launch Sauerbrotten to run it on my computer, Sauerbrotten has two different executables. One of them is Sauerbrotten-client, one of them Sauerbrotten-server. And honestly, I could search for either one of them. I just chose that particular binary. If it exists on the system, I know the package Sauerbrotten has already been installed on your computer. And that's how I know I can mark that with a asterisk or not, depending on whether I actually locate that binary. So again, the first column, the keys are the package that gets installed. The second column would be the executable binary to search for on the system to see if it's already installed. So I have that games function. And if I scroll up, of course, I've got the office function, which is the same multimedia, the same other internet, the same browsers, the same. So all five of those just do the same thing. Title, text, they create their array of programs that appear in the menu. And all of them have this line here, program choices and then selected programs and then exit or install. So they run these three functions. So if I keep scrolling back up, it's like everything is in reverse order. Well, those three functions that they run, program choices, it basically creates our menu. So the way this particular function works is we're creating an array choices. It's an empty array, but we're gonna add stuff to it later. You can see down here, what we're gonna do choices plus equals. We're gonna append some stuff to the choices array. So we start out with an empty array, but we're gonna add stuff to it. And we're gonna add three values to the array each time. We add key, spacer, and either the word off or own, depending on whether that executable binary exists on the system or not. Because when you mark it on, you get the asterisks. When you mark it off, you don't get an asterisks. So whip till when you're creating your windows takes three values. You have to give it three different strings with the last one being the word owner off all caps. The first value is the title. It's what appears next to the checkbox. And then if you wanna give it a description, that would be the second value. Even if you don't give it a description though, you still have to include the second value. You could just leave it empty. What I've chosen to do is because I don't want some of these dialogue boxes to be really small. I want them to be spaced out a little bit. I have actually added a spacer, this variable spacer. And you can see what I've done here. Spacer equals this for loop for I integer in a sequence of numbers, one through 42. I want you to take one through 42. And then I want you to echo that at a number of times as spaces. I want you to basically use a spacer of 42 spaces. What I'm doing here, actually let me just go back and rerun the script. So you can see what I base this off of is currently the longest program I'm installing is this one here, Microsoft-edge-stable-bin. And I wanted 42 spaces just to space that out all the way to the end of the window because the window is 78 spaces in length. I specified that. I could actually change that if I wanted to. But otherwise, this blue section of the menu would only go up to about right here. And it just made the window look weird. That's why I added the spaces. Or again, you could add a description behind each of these as well if that's what you wanted to do. Now let me cancel through all of these and get back to Emacs. Now one neat little thing is checking if the executable binary already exists on the system. That's how I know to add the asterisks. And I do that with this if statement here. What we're doing is we're running a test essentially. We're testing if the executable for command-v name of key exists. So I go back to the terminal if I zoom in a little bit. So if I do command LS, right, it runs the LS command. People will often use the command, you know, name of command to bypass their alias because my LS is actually alias to exa. But if I do command LS, it's actually LS, right? Well, all I'm doing is I'm running command and then the checkbox is array and the key value. So I'm going back down here. We'll take browsers, for example. We're taking each of these key values, right? That's the first field. And we're running command name of this field. And we're running a check basically to see dash x. What we're doing is we're checking if that command, so command Firefox, is it in the path and is it executable? If it's not in the path and it's not executable, Firefox is probably not installed on the system. So if it's not installed on the system, Firefox will be marked off. Meaning there's no asterisks in the menu. Now, if I run the check and Firefox is part of the path and is executable, it will be marked with on. I hope that makes sense. So that's how we get the menu set up, the space correctly and the asterisks and then the next function selected programs here is actually creating the whip tail window. You can see it's very simple. It's really one line, but I've spaced it out to be four lines because I've got the line breaks here with the back slashes. But you do whip tail and I've added a title, dash dash title and the title is the title variable. Remember each of the functions I created, browsers and other internet and multimedia, each of them have a title. And then dash dash checklist and then text. Remember each of those functions of the five main windows has a text box as well. And then I've got the size. 22 lines is how long it is, 78 characters wide. And then 12 is the check box itself. So if I added 15 things to one of those checklists, what will happen is you'll get a little scroll bar so you could scroll through the rest. I can actually show you this in action. But instead of 12, I make this eight. Let's go back to the terminal. I'll rerun whip tail here. And now I can actually scroll down. It's kind of hard to tell that there was a scroll bar here. Probably should color that a little differently. But you can actually scroll through the list. See, this one actually looks a little better. I see what the problem was on the first screen. My spacer went into the scroll bar. So I need to fix that. But you can see now we got a proper scroll bar where if you go through the list, it's obvious. What is going on? All right, so I should fix that. What I'll probably do right now, we'll just fix this on camera. Let's make the spacer a little smaller. Let's make it 38. Let's go back to the window. Again, just trial and error. And now that's actually perfect, right? With one space to spare, right? But that works. It's a little too much space on the wrist, but I couldn't get it quite right on all of them. But that works. That's good enough. So we got whip tail dash, dash, title, the title, dash, dash, checklist, our text. And then the size of the window. And then the next thing I feed it is the choices array. So this is what actually is in the checklist. So it's basically if I go back up program choices and inside it, we had the choices array where we did the for loop, getting the spacer and then the owner off, you know, checking if the executables, all that. That is what is populating the actual list. And then finally, you have this weird stuff here, which is another peculiarity with whip tail that you really don't have in dialogue. For whatever reason, whip tail does some strange things with standard out and standard error. I think it swaps them around. So what's happening here? I think you have to swap them back to the correct streams. And that's a little weird. I actually found some of this if I go back to the documentation on this website here at wikibooks.org. I scroll back, they had some examples of some checklist and some radio lists. And you can see right here is basically kind of what I had. So, you know, they've got it all on one line instead of broken up. But at the end, they have three and then greater than sign and one and one greater than sign and two, two greater than sign and three, they're just swapping all the standard and standard out standard error. They're just directing the streams to different places. And it's kind of weird. I don't know why they do that. I have seen complaints online doing some research about whip tail that some people really don't like the way it redirects standard error. But that's the way the program works. So just know that. And then finally, I have dysfunction here. Exit or install, I found this online, I think in the whip tail documentation. But all this does is it checks the exit status for the program. So if the whip tail box works correctly, so if I select some stuff and hit okay, it should exit with a code zero, meaning the program succeeded. Now, if the exit code is anything other than zero, it's a failure of some kind. So I have this if statement. If the exit status is zero, meaning the program succeeded, I want you to do this here. I want you to get a list of all the programs. So this would be the ones that we marked with a asterix and then I want you to run some said substitution because I want you to get rid of all the quotation marks around them, because I'm gonna feed these into Pac-Man. Or in this case, I'm actually gonna use Paru because some of these are AUR programs. And then Paru is going to install the programs that were marked. And then I've got the two pipe symbols. So this is a or. So Paru is either gonna install the programs or it's gonna basically have an error. If the error is gonna be, I just want you to echo it failed to install the required packages for some reason. Then the else part of the if statement. So any exit status other than zero is a failure. So just echo user selected cancel because that's what the failure is gonna be. It's me not choosing. Okay, it's gonna be me choosing cancel. So again, so if I, for example, hit okay here. So tab down and hit okay, let's exit status zero. So it's going to run Paru install all of these programs or it's gonna at least try to, let me give it my sudo password. And it didn't install them. It tried to, but they were already installed. So it just bypassed it. But the next part here, if I hit cancel, that'll be an exit status of a code other than zero. So it will not try to install any of these, right? So I don't go back to the terminal and get Paru trying to run an install. So that is how that works with the exit statuses. And I know some of this is a little complicated. Again, I spent several hours over the last couple of days working on this script. Let me zoom back out. It's actually kind of lengthy. And I know the way I wrote it is probably not the best. Again, I'm not much of a programmer and I do a little bit of bash scripting. I don't do a lot of bash scripting, but this was fun. I've got to say making this was really nice. And I may, I'm seriously thinking about adding this to the DTOS script, the installation script because I know a lot of people do have some issues with DTOS the way it's currently set up because so much of the input is done at the command prompt. For example, when you get to what window manager would you like to install? It asks you right there in the TTY at the command prompt. Well, I could do a whip tail, little dialogue box. Hey, which window managers do you want to install and have a list? Xmonad, Awesome, Qtile, whatever else I want to add to DTOS eventually. And that just makes it a little more user friendly. It's also obvious when you get to that section of the installation, because if you're not actually watching DTOS install, sometimes you'll get to that yes or no question about installing Xmonad or the yes or no question about installing Qtile. And it's not obvious that the installation has paused and waiting for input, but with these whip tail boxes that'll pop up, it's obvious. Hey, you need to come answer this question right now. So that's kind of what I've been thinking is adding these whip tail dialogue boxes to make things a little more user friendly. Originally, I was actually planning on making the entire DTOS installation nothing but command line. Nothing but the command line interface, because I thought that would be simpler, at least simpler for me, because I didn't have to worry about a UI experience. But the more I see people playing with DTOS, the more issues I get on GitLab, the more I see people trying to install DTOS on video, the more I realize I need to make this thing, I guess, a little easier, right? A little more obvious what is going on. So whip tail is pretty cool. For those of you that want this example script, what I'll do is I'll actually push this example code. Let me get back to the desktop here. I'll push this example script to the DTOS repository. So go to gitlab.com slash DTOS slash DTOS and you will find whip tail dash example.sh over on that GitLab. Now, before I go, I need to thank a few special people. I need to thank the producers of this episode. Gabe James Maxim, Matt Mehmet Mitchell, Paul Royal West, Armored Dragon Bash, Potato Chuck, Commander Hungry, George Lee Methos, Nate Erion, Paul Peace, Archon Fodor, Polytech Realities for Less, Red Prophet, Roland Tools, Devler, and Willie, these guys, they're my highest tier patrons over on Patreon, without these guys. This episode about whip tail would not have been possible, the show's also brought to you by each and every one of these fine ladies and gentlemen. All these names you're seeing on the screen right now, these are all my supporters over on Patreon because I don't have any corporate sponsors. I'm sponsored by you guys, the community. If you like my work and want to see more friggin' open source software, subscribe to DistroTube over on Patreon. All right guys, peace. Whip it, whip it good.