 One of my favorite kinds of videos to make is where I solve a real-world problem through the use of shell scripting, because a lot of Linux users, especially those of you that are new to Linux, shell scripting seems like it's something that's really hard, it's complicated, you know, you've got to learn a ton of stuff to get this stuff to work, but really, once you start playing around a little bit with the terminal and the command line, you can quickly figure out a lot of the basic command line utilities that are needed to create these shell scripts and you can really start solving a lot of problems through the use of shell scripting. So what is the problem that I'm gonna solve today? Well, it involves your keybundings in your tiling window managers. A lot of people want an easy way to bring up a list of all their keybundings for their tiling window manager and the reason people ask about this all the time is because there's one tiling window manager that really gets this right, the awesome tiling window manager. The awesome window manager, you hold the super key and a window pops up and it lists all your keybundings for the awesome window manager and now everybody that runs all these other tiling window managers want that same feature in their window manager, but of course these other window managers don't have that feature. Well, you know what? We can kind of create something with a simple shell script. So let me switch over to my desktop and today I'm running the Xmonead window manager and I've already pulled up my Xmonead config here inside Doom Emacs because what I want to do is I want to be able to grab all of the keybindings and the commands they run from my Xmonead config. So what I'm gonna do is I'm actually just going to page down here. Actually, I went a little too far. This is my keybindings. It's in this statement that says my keys equals and then I've got a very long list of keybindings here in Xmonead. What I would like to do is find some way to pull all of these keybindings out. You know, just basically everything that was in that my keys block. I don't need the rest of the config obviously printed out because we just want a window that pops up that shows us the keybindings. So what's the best way to do this? I don't know the best way. I'm not a professional programmer. You know, I just do this as a hobby, but I know that SID has the ability to give you a number of lines from, well, you give it a starting statement and an ending statement and it pulls out all the lines from each of those statements. So what I'm going to do is I'm just going to create some special comments here. Now, comments in Haskell begin with dashes, two dashes. So I'm going to do dash dash space. And I'm just going to do start underscore keys, all caps. And then I'm going to escape. I'm going to page down to the end of my keybindings here. And let's go back up. That was the end of the keybindings. And then I'm going to just go ahead and create one more comment here. I'm going to do dash dash space and underscore keys and escape. So let me go ahead and save this to my xmonad.hs config file. So I went ahead and did colon w to write and I'm going to do a keybinding I have for org babble tangle here inside doom emacs. And then now that I've saved that, what I'm going to do is I'm going to open a terminal. Let's go ahead and zoom way in here in the terminal as well so you guys can see this. What I'm going to do is I'm going to run the command said dash in and then inside single quotes, I'm going to do slash start underscore keys because that's the the starting comment that we wanted. So I want to pull all lines starting with start underscore keys and then slash comma slash and then n underscore keys and then the ending slash and then the command I want to run on this I want to run the print command P. And then we need to give it the path to my xmonad config. So that would be in my home directory slash dot xmonad because it's a hidden directory slash and then xmonad.hs. And that prints out, let me make this full screen that prints out every line between start underscore keys and n underscore keys. Now of course, many of these lines don't we don't need necessarily because some of these are just comments really some of them are useless comments we could get rid of some of that. We could also get rid of some of the extra notation and syntax and things we could clean this up a little bit and that's what I'm going to do. So what I'm going to do is I'm going to up arrow and I'm going to run the same said command, you know to get all of these lines from start keys to end keys and then I'm going to pipe it into grip because grip will allow us to do some interesting stuff here. For example, if I wanted to, I only want to get the lines that actually have the actual key bindings and the actual lines that have key bindings looks like all of them start with comma space opening parentheses and then a double quote. So why don't I just grip that? So we do grip and then inside single quotes comma space opening parentheses double quote. And now when I run that it's a lot cleaner right because all of those comments which were lines that started with dash dash or no longer output it here. Actually looking at it that's not entirely true. We do have some commented lines that were returned because some of the commented lines that started with dash dash also had the the string comma space opening parentheses double quotes because these were key bindings that I've disabled by commenting them out. I don't want those returned if I'm not currently using the key binding you know it's a commented key binding I don't want that to be listed either. So I'm going to up arrow and we did grip. Let's go ahead and grip one more time. I will pipe all of this into grip one more time and this time I'm going to do a inverse grip. So I'm going to do dash V meaning return all the lines except the ones that have this string. So I'm going to do inside single quotes again I'm going to do dash dash space and then comma space opening parentheses single quotes so these lines here that started with that string I want to get rid of those so return all the lines that don't have this pattern that's what the dash V flag does for us and now that did not quite work and I actually got an error message because grip does not like the dash dash pattern we need to escape that so I need to do a backslash dash backslash dash that actually grip will understand that as being dash dash in the document. Now when I run that we get exactly what we wanted. It looks like I still have one more commented line that didn't get filtered out is because I didn't keep the same pattern instead of dash dash space comma space that particular line is dash dash comma without a space I could actually just fix that in the config since that's really my fault for not keeping the same pattern for all of my commented lines I'm just going to fix that right here in the config and now when I run the grip command again. Now that commented line is actually no longer returned so I'm just going to scroll through here yeah it doesn't look like we have any commented lines now so already this is a pretty clean layout it gives me the key binding and the command it runs and then at the end of the line I did have some comments for those of you that are using my config to more specifically explain exactly what the commands are in case you don't understand you know what the actual commands in Xmonad do for example if you didn't know that the spawn Xmonad restart command restarts Xmonad I went ahead and commented it out specifically you know so explicitly for you guys now one thing that is a problem I noticed is the very first key binding that is returned here is actually the second key binding in my Xmonad config let me make the Xmonad config full screen you see because that's the one key binding that doesn't start with comma space of opening parentheses it actually starts with opening bracket space opening parentheses so I need to take that into account here so what I'm going to do I'm going to up arrow and let's go ahead and add a rule for that what I'm going to do is I'm going to go back here to this first grip here I'm going to add the dash E flag because we're going to do multiple grips here so I'm going to do dash E again and then inside single quotes I want to grip for the opening bracket I have to escape that so do a backslash bracket space parentheses and then I think that should work now if I run that and let's scroll back up and see if we actually get now we actually get the very first key binding as well so now we're actually seeing every single key binding now I've still got some work to do on cleaning this up but this single line at the command line is going to start getting very long so what I'm going to do is I'm actually just going to do a copy because let's go ahead and put this in a real script so I'm going to go ahead and create a new file here inside Doom Emacs so I'm going to do a space period because inside my dot Xmonad directory which we're currently in because we're looking at Xmonad dot HS I'm going to go ahead and create a shell script I'm going to name it Xmonad underscore keys dot SH and then it creates this new bash script here because by default I've got my Emacs setup to where anytime I create a shell script it gives me the user bin ENV bash shebang so it's going to be a bash script let me zoom in and what I'm going to do is I'm just going to paste what we had had in the terminal before and let's go ahead and clean this up so it looks a little better so let's do some line breaks so in shell scripting or even at the command line running this you could actually create some line breaks with the backslash character so that's what I'm going to do is I'm just going to go ahead and put a few backslashes just to make this a little more readable I'm going to go ahead and do colon W to write that and I'm going to open up a new terminal here and I'm going to cd into dot Xmonad that directory if I did a ls you see Xmonad underscore keys so what we need to do is run the command chmod plus X because we want to make this script executable because it will not run if it's not executable and now that I've done that you know we could actually run this if we wanted to and you see how that works let me go ahead and zoom in on this terminal because this will be the terminal we use from here on out let me go back to the other terminal here I'll just close that out now we'll just play around in this shell script instead of doing this at the command line it'll be easier to read this way now one thing I didn't like about the output from this command is the fact that every line has a whole bunch of leading spaces so I want to get rid of that so and the reason it has leading spaces is because the lines it's actually pulling out of my config have leading spaces because they have to you know I can't have these lines starting at the beginning of the line because Haskell's really picky about spacing so I actually need the spaces in the config file but I want to get rid of the spaces when I actually have this printed out in the terminal and we can do this with a regular expression here what I want to do I probably want to do this with SID let me get back into insert mode and I'm going to pipe all of this into SID this time and we'll do SID-E because we may do multiple SID statements and then we're going to do single quotes S because we're going to do a substitution what do I want to substitute I want to substitute the carrot symbol which signifies the beginning of the line and then inside brackets I want to do a space or tab and then the asterisk symbol what this signifies is find the beginning of the line if everything at the beginning of the line is tabs or spaces I want you to replace it with what with nothing and I think that's really all I want to do there so let me go ahead and write and then get back to the terminal and let's go ahead and rerun our script and see if that actually works it did it removed all of those leading spaces to clean it up a little further I think I would want to get rid of the leading comma space on each line as well so let's get back to the script here and get into insert mode I'm just going to do another dash E we're going to continue with SID substitutions here and then we're going to do a substitution for the comma space parentheses and then what we want to substitute that for is just parentheses and then do the trailing slash at the end and if I do colon w and then get back to the terminal and run that that did not work because I obviously made a mistake here because I didn't add the backslash to signify a line break there so let me put that in its place and then go back to the terminal and rerun that and now we get rid of the opening comma space that was at the beginning of each line of course remember there is the one line that's not going to look right because the very beginning line had a bracket and of course we could take that into account as well if I get back into the script once again let's go ahead and create a new line here and we'll do dash E because we'll continue on with SID this time what are we going to substitute we are going to substitute an opening bracket space opening parentheses and we're going to substitute that with just opening parentheses and then do the trailing slash Emax annoyingly anytime you do anything with brackets parentheses it likes to add the closing one which is great sometimes but in this particular case it's actually getting in my way I can actually turn that off but I won't bother and now when I run the script let's see if it fixes the very first line and now the very first line looks the same as the rest of the lines now one thing I don't like about this gigantic list of key bindings is it's all one big block of text there's no real breaks one thing I would find interesting is if I could actually group the key bindings which I've grouped them in my config file right I've grouped them by category for example all of the d-menu key bindings are in one section and all of the Emax key bindings are in one section etc and I want to keep that and I would like those comments for the types of key bindings to actually be outputted as well but remember we stripped out all the comments everything that began with dash dash but I think we could fix this if we just add a specific string that we can you know do something with grip or said with later so once again I'll do all caps and I'll just create a tag essentially I'll do kb for key binding underscore group so these will be key binding groups here and then the name of the group in this case these are x-monad key bindings and I could go down here and do the same thing so once again I'll add kb underscore group what I probably should do is just get into visual mode here and actually yank that just copy it that way I can go down here and just paste it a million times so that I've got each category here I'm going to write that I'm not going to go through and do it to every single group here I'll just do four of them just to see if this actually works and then what I want to do is get back into our script what I want to do is I want to go back to where we were gripping with the dash e flag I want to create a new line let's do dash e one more time this time I want to grip this particular string kb underscore group and let's write that let's go to the terminal run the script and now let's go back to the top of the document and see if that worked for us and it did not so obviously we made a mistake there obviously I needed to add a pipe and then of course let's make sure we get the line break there with the backslash let me write that again so that was just a dumb mistake on my part let's rerun the script and now we get an error the dash e command is not found so now we had the pipe on this line that doesn't need to be there so we only need to pipe when we're actually piping into grip or said we don't need a pipe symbol when we're just continuing on with dash e so now let's run the script the script actually works this time let's see if we actually have the group headings the lines with the group names no we do not so we keep making mistakes but that's fine I leave all the mistakes in the videos because that's part of learning is seeing somebody screw up and you guys hopefully don't do this when you're doing your scripting but honestly when you're doing one of these scripts on the fly there's a lot of trial and error with them and looking at this I really think this should have worked I'm not seeing the error the others you know when they didn't work I obviously I immediately spotted the error but this looks like it should work so what I'm thinking yeah I know what it is I'm an idiot I changed my config file I didn't write it and then I need to run a org babble tangle to have that output to xmonad.hs and I'm betting now the script actually works if I go back here and run the script and let me scroll back up and now yeah we actually get the group name xmonad run prompt other dmenu prompts of course we also get dash dash kb group so now what we need to do is get into the script and what we need to do is get rid of dash dash space kb group on those lines I think how I want to play that is I'm just going to go ahead and do this with SID so I'm going to add the backslash it's for a line break just continue on dash e here and then inside single quotes we'll do a substitution again what am I substituting I'm going to substitute dash dash space kb underscore group space because I want to get rid of the space after kb underscore group as well and then slash and then what do I want to replace this with I actually want to replace it could I replace it with a new line slash let's see then if that works I'm going to write that let's go ahead and get back to the terminal and run that and see how that looks scroll back up and that looks really really nice right because I added a line break before the group name now one thing I don't like is I don't like that I have the comma separating the key binding from the command it runs I'd rather that not be a comma I want it something more something that stands out a little bit more visually I think I'd rather change that maybe to a colon so let me get back into the script and what I'm going to do is I'm just going to go ahead and add another SID substitution so let's go ahead and substitute a double quote comma space because that was the pattern and I would rather that be a double quote space colon space and then I'm going to do the trailing slash and then the trailing single quote and let's see if that actually works for us so let me rerun the script and yeah I think that is a little bit more easier to read I think that visually that stands out a little more than having that comma right behind the double quotes now we have space colon space and if I wanted this to line up even better what I could do is I can actually change the space I could do something like a change the space to a tab and let's see how that looks rerun the script and yeah and now that's even better as far as visually separating the key binding from the commands now the next thing I want to do is I don't want this information to have to always be output in a terminal I would rather this output in a graphical window a dialogue box and on linux the most common dialogue box program is a program called yad which stands for yet another dialogue and what I'm going to do is we're just going to pipe all of this information and let me go ahead and add the pipe symbol and I'll go ahead and create a line break as well I'm going to pipe this into yad dash dash text dash info and that is the type of box we're creating with the yad dialogue box program is it's a text info box because there's a whole bunch of windows you can create with yad you can create message windows and and things like that so I'm going to go ahead and do a colon w to write that and then go back to the terminal and now run the script and it opens this yad dialogue box it opens it full screen because we were in full screen mode but if I was in tiling mode it would just be a standard tiling window now I don't want that to actually be tiling I don't want it to be full screen either what I would like is I would like to have that open at a specific size and centered on the screen so what I'm going to do is I'm going to get back into insert mode here and another thing I want to do is I want to change the colors because I didn't like the gtk color scheme of those windows I'd rather it respect kind of like my emacs color scheme or my terminal color scheme and in this program yad you can actually specify a background color and a foreground color so I could do dash dash back equals and then give it a background color I'm going to do 282c34 that's the background color that I use in emacs and in my terminal color schemes and then I'm going to do dash dash four equals for a foreground color and for that I'm going to do 46d9ff and then what I want to do is do dash dash geometry equals and I want this to be 1200 pixels by 800 pixels in size and then let me do colon W to write that and then let me go ahead and run that and see how that looks it's still full screen if I was in tiling mode it would still be tiling the problem here is you know setting the geometry works fine if we were in a floating window manager but a tiling window manager always forces things to tile so this is not a problem with the script necessarily it's a problem with my xmonad config I need to set a window rule that all yad windows are floating so what I need to do is get into my xmonad config and then I'm going to page up to where I have some window rules settings and you see things like class name equals and then the name of the the windows and then do float these are all the windows that I want to always be floating such as gimp for example class name equals gimp do float so I'm just going to go in here and I'm going to yy to copy and p to paste and then I'm going to create class name equals and I'm going to do yad I'm assuming that the window name is actually yad and then I'm going to do do float but really what I want to do is do center float because xmonad has the ability to force a floated window to also be in the center of the screen now if I do colon w to write that and then let me write that to xmonad.hs and I'm going to restart xmonad and I get a error message and the good thing about xmonad is it's really good about error messages as far as it tells you exactly what the problem is the problem is do center float I didn't import a library that has a do center float module it actually tells me that right here it tells me I should have imported xmonad.hooks.managehelpers do center float so let me get back into my config I'm going to go to the top of the document here because that's where my imports are and I need to import xmonad.hooks.managehelpers which I've already got but I specified only two modules is full screen and do full float I need to go ahead and add do center float let me go ahead and write that and xmonad restarted without any errors so now when I run the script it should open in the center of the screen so let me just run that from the terminal here and I'm in tiling mode and let's see if it actually yes it forces the window centered in the middle of the screen with 1200 by 800 pixels for the size and it respected my background color and the foreground color I chose so that is how I would do that the last thing I probably would do for purposes of this video I don't want to run this from a command line I don't want to run this from a run launcher you know I want a key binding to where I hit a key binding and this window with all of my key bindings pops up so what I need to do is I need to put that of course in my xmonad config so let me go down to where all of my key bindings are and I'm just going to add a new one let me find the very beginning of my key binding list because it needs to go in the key binding group for the xmonad key bindings so I'm just going to go ahead and create a new one so I'm going to do comma and then inside parentheses here inside double quotes I'm going to do mod shift slash now my shift slash is really mod question mark because the question mark is typically the key you hit in many programs to get help so it makes sense for this key binding to actually be mod shift slash or mod question mark and I need to do a comma behind that and then the command we're going to run the command we're going to run of course needs to be spawn and then what are we spawning we are going to spawn the path to that script which is in my home directory slash dot xmonad slash xmonad underscore keys dot sh and let me escape and let me write that and now let me restart xmonad and now let me do mod question mark and now mod question mark brings up the window with our key bindings how cool is that that that's very nice and of course I could clean this script up a lot more and make the you know this look a little bit better because honestly I could format that a lot better but really this works I mean if you had a problem figuring out what your xmonad key bindings this works I mean I can easily read this to figure out what key binding does what and of course just because I did this in xmonad I mean you could write a script to grip and set out all that information for cutal or i3 or bspw or whatever window manager you use now obviously that was a very quick and dirty script I didn't spend what 10 15 minutes and we just kind of going at what we're winging it right and I did everything with sed and grip which I purposely was trying to do sed and grip I was trying to actually avoid using alt because I use typically use alt a lot in my scripts and people complain man you using alt why didn't you use sed for that why didn't use grip for that well here you go and honestly I'm not even sure shell scripting is the best way to accomplish this ideally what you would want to do is if you actually knew haskell because xmonad's written in haskell the config files written in haskell it would be great if I knew enough haskell where I could actually get this information by adding some haskell code to my config but I am nowhere near a haskell master it's a lot easier just to quickly throw together this quick shell script now before I go I need to think a few special people I need to think the producers of this episode as he gave James Mitchell Paul with Sikami Allen Chuck Gert David Dylan Gregory High Co Erion Alexander peace arch and fedora polytech raver red prophet Scott Stephen and Willie these guys they're my highest tiered patrons over on patreon without these guys this episode that you just watched would not have been possible the show's also brought to you by each and every one of these ladies and gentlemen as well all these names you're seeing on the screen each and every one of these ladies and gentlemen help support me over on patreon because I don't have any corporate sponsors I'm sponsored by you guys the community if you like my work you want to help me out please consider subscribing to distro tube over on patreon all right guys peace and yes I'll push the script to my get lab