html lang="en" { head { HEAD } body { header { div .head { h1 {-Dmenu is a Godsend} INCLUDE(nav.gsp) } figure .quote { blockquote { p {= Because @code{-dwm} is customized through editing its source code, it’s pointless to make binary packages of it. This keeps its userbase small and elitist. No novices asking stupid questions. } } figcaption {-https://dwm.suckless.org} } } main { h2 #simple {-Simple Software} p {- In a @a href="/blog/gsp" {-previous article} I talked a bit about software simplicity, or perhaps maybe the lack of it that exists in the world. One of my favorite parts of UNIX-like systems is the composability of command-line tools. Instead of having giant monolithic programs that do everything, you have various small domain-specific tools that all use a common interface — standard-input and -output. The following is a good example of this: } figure { pre { FMT_CODE(compose.sh) } } p {- I have a YAML file on my system with various fun quotes, and I like to have a quote-of-the-day that’s displayed when I open a terminal. I can make use of the @code{-yq} program which is specialized in querying YAML files to extract the list of quotes from the file. I can then use the @code{-shuf} program to shuffle the quotes and pick one at random, and finally I can use the @code{-tr} program to translate null-bytes to newlines. } p {- Notice how all three of these tools are very specialized to a specific domain; they don’t try to reinvent the wheel, instead offloading the tasks they aren’t specialized to do to other tools. @code{-yq} doesn’t waste its time with functionality to shuffle lists of items because you can do it with @code{-shuf} instead. This mindset of composability allows you the user to create tools that are more powerful than they could have been otherwise. Instead of hoping that all your tools offer support for shuffling items @em{-and} hoping that they can shuffle things in the specific way you like, you can just use the one single shuffling tool @code{-shuf} everywhere. } p {- In my example I used @code{-shuf} to pick a random quote, but I could similarly use it to pick a random song from a playlist, or to pick a random image to use as a desktop wallpaper. } p {- So with the composability of the UNIX environment being such a great thing, it blows my mind that people are still writing software such as @code{-kitty} that try to do absolutely everything in one giant monolithic program instead of keeping focused to the task at hand and allowing the user to extend their tools to add in the functionality they so desire. } figure { figcaption {-Kitty’s Unicode input screen} img alt="Kitty’s Unicode Input" src="unicode.jpg" style="width: 100%;" {} } p {- Some of you have surely already figured out what my issue is with what Kitty has done here, and why I think this is shitty software design. For those that haven’t, allow me to ask you a question: @em{-what would be better than Unicode input in your terminal?} } p {- The answer is simple: @em{-Unicode input everywhere.} } p {- Why should you be limited to Unicode input in your terminal? What if you’re texting your friend or sending an email, and want to include a Unicode symbol such as ‘™’, or want to properly refer to a site you visited such as Ta’ Ħaġrat? Perhaps you even have a friend whose surname is Mäkelä. Or maybe — you just want to send your friends a middle-finger emoji sometimes. } p {- Wouldn’t it be nice if you had a @em{-global} menu for Unicode input? Well turns out it’s actually really damn easy to do yourself, and renders all that Kitty code absolutely useless. } h2 #scripting {-Writing the Script} p {- The first thing you’re probably going to need if you want to have your own Unicode-input tool is a list of all the Unicode characters out there. Luckily for you, I already went through the hell that is the @a href="https://unicode.org" {-Unicode website} to find it for you. } figure { pre { FMT_CODE(download.sh) } } p {- You can check out the file for yourself if you want. It’s got a bunch of information in it — a lot of which is really useless for our purposes. There are also a bunch of control characters and other things in there that I personally don’t care for, so those can probably be removed too. If it tickles your fancy, I’ve written a @code{-sed} script to clean up the input into something a bit nicer: } figure { pre { FMT_CODE(cleanup.sed) } } p {- After processing, your Unicode data file should look something like this: } figure { pre { FMT_CODE(unicode.txt) } } aside { p {- You know how I inserted that sample of my Unicode data file you see right above this? By using a small- and simple command-line tool in the form of @code{-head} to grab the first 10 lines of the file, and then using another small- and simple command-line tool in the form of @code{-wl-copy} to copy those 10 lines to my clipboard. Take that Kitty. } } p {- Now that you have your data file, we can begin scripting. The first thing we want is to get all of the names of the Unicode characters. Turns out that is a very easy task thanks to the @code{-cut} utility. We can split each line on a semicolon and extract the second field with a simple command, and then we can compose it together with @code{-dmenu} or your preferred clone of it to present the user with a graphical list of items they can pick from: } figure { pre { FMT_CODE(dmenu.sh) } } p {- Notice how we can simply compose @code{-cut} and @code{-dmenu} together, and just assign the result to a variable. We can do this because these are sane programs that read from standard-input, perform some simple, basic task, and then print a result to standard-output. One tool to parse a file, and another tool to let the user pick a selection. } p {- We have the users selection now, the @code{-$name} variable holds the name of the Unicode character that the user selected. All that we need now is to actually get the Unicode @em{-character} of our choosing. Luckily this is @em{-also} incredibly easy thanks to composition: } figure { pre { FMT_CODE(program.sh) } } p {- Congratulations! That entire script, which can be easily condensed down into only 2 lines of code is all you need to create a graphical interface that allows you to pick a Unicode character, and then copies your selection to your clipboard — and it was all done by taking simple tools and combining them to make a greater application. } p {- So next time you’re developing software and want to add a new feature, just pause and think for a second. Do you @em{-need} that feature? Can it be done in a better way? It is possible to generalize your feature to where it is useful outside of just your specific application? Don’t make the same mistake Kitty did. Allow me to leave you with this quote: } figure .quote { blockquote { p {= The talk reviews reasons for UNIX’s popularity and shows, using UCB @code{-cat} as a primary example, how UNIX has grown fat. @code{-cat} isn’t for printing files with line numbers, it isn’t for compressing multiple blank lines, it’s not for looking at non-printing ASCII characters, it’s for concatenating files. } p {= We are reminded that @code{-ls} isn’t the place for code to break a single column into multiple ones, and that @code{-mailnews} shouldn’t have its own @code{-more} processing or joke encryption code. } } figcaption {-USENIX Summer Conference Proceedings, 1983} } h2 #good-bad {-The Good, The Bad, and The Ugly} p {- I would like to take a moment to point out some examples of composability done right, and some examples of features that are actively harmful in the pursuit of the UNIX ideal. } h3 {-Ls — Bad} aside { p {- This is already referenced in the above quote, but I added that quote after this section was already written. } } p {- The @code{-ls} program is one of the most useful ones found in the UNIX environment. It has a simple job to perform and it does it well. It lists files in a directory. So what’s the issue then? Well let’s see what happens when you combine @code{-ls} and @code{-cat}: } figure { pre { FMT_CODE(ls-1.sh) } } p {- Ok… that looks about right. We invoke @code{-ls} and we get a listing of the current directory, newline-separated. Well look at what happens when we don’t compose it with another command: } figure { pre { FMT_CODE(ls-2.sh) } } p {- Yeah… it decided to ‘prettify’ the output by putting everything on one line. If the input contains enough items it columnates them really nicely for you. Here’s an example of what it looks like when I run @code{-ls} in my screenshots folder: } figure { pre { FMT_CODE(ls-3.sh) } } p {- Now don’t get me wrong, I like the fact that I can see more than one item per-line. But why is this specific to @code{-ls}? It could actually be really useful to be able to take arbitrary input and columnate it in such a form for easier consumption. The @code{-column} program does exist on Linux systems, but it is far inferior to what @code{-ls} provides. In the ideal world, @code{-ls} would simply display one filename per-line with a better @code{-column} command, and you could compose the two to get a nicer viewing experience for your files. } h3 {-Tabbed — Good} p {- What is one thing that almost all your graphical applications have in common? They all have tabs. Your web browser has tabs, your terminal probably supports tabs (and if it doesn’t, I bet you use @code{-tmux}). Your code editors have tabs, and even modern email-clients have tabs. Now let me ask you: why do we always reinvent the tab? } p {- Suckless — the same people that brought us @code{-dmenu} — also created a lesser-known application called @code{-tabbed}. You can @a href="https://tools.suckless.org/tabbed/" target="_blank" {= find it here }. It’s quite a simple piece of software. You simply run it together with another program (such as the @code{-st} terminal) and it adds tab-support to it. Not only does this reduce code-duplication, but it also is beneficial for you the software user as it means you get a consistent UI with consistent-behaviour and -key-bindings wherever you go. } } footer { FOOT } } }