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 }
}
}