On having a programming toolbox — part 1
When I was younger, I used to scoff at the idea of having a programming toolbox.
"I am a generalist," I'd tell myself, "I can learn a new framework or library in a week! Learning is fun!"
Or perhaps.. "Who needs a toolbox; toolboxes are for older developers that are just stuck with the same old tools!"
Well. I'm older now. And perhaps I've lost some of that "flexibility of mind" my younger self patted himself about. Or frankly, I might have just lost the patience of having to learn a whole new framework or tool for a small one-off project.
Whichever the case, I recently1 wisened up to the realization that I do, in fact, have my own programming toolbox: a set of tools that I consistently reach for, regardless of task, project, and situation. These are tools that I have adjusted my workflow to, tools that I have familiarized myself to through repeated use, and tools that are now almost indispensable to me efficiently using a computer.
And honestly... the list of such tools is a bit lengthy, which is why I've decided to split it into multiple articles.
This one will be about the core tools in my toolbox, tools without which I... don't really want to use a computer:
The core tools in my toolbox
Linux
I can't skip mentioning the operating system I daily-drive: Linux. Much of the tools that I use don't work near as well on Windows (or even Mac), and it's not those tools' fault: without the solid foundation of POSIX APIs and the simpler interfaces afforded by open-source software, it is markedly harder to make a tool that works well.
For just one example: it's faster to start new processes on Linux than it is on Windows. That seems like a minor gain at first glace, but it actually enabling you to run a lot of small programs in a chain to complete a task instead of having one specialized mega-tool that does everything you need. And that ends up shaping a lot of the tools I use: smaller tools that focus on one part of what I need, arranged so they are more than the sum of their parts.
Listing Linux before a bunch of Linux-friendly tools feels a bit like listing steel before listing all my favorite steel-made pickaxes and shovels, and hence unnecessary. But I don't think that's avoidable: I've been spoiled by how well steel tools handle everything, and no amount of shiny brushed aluminum can change my mind. 😁
KDE, Yakuake, Latte-dock
One of the first things to greets me when I launch my Linux machine is a lightly-customized KDE desktop.
If I had to think, I'd say there are four features of my KDE setup that I won't be able to live long without:
Workspaces. I have a 3x3 grid of "screens" I can switch between at will by holding down Ctrl-Meta and an arrow key. These workspaces wrap around (e.g. going left from the left edge puts on on the right edge), and I have a general idea of what each workspace is assigned to—allowing me to quickly switch between applications, with a lot less hassle than Alt-Tab-ing between windows (or worse, using a mouse to pick them from the dock).
Active corners, all bound to the Grid action. Active corners/Screen edges is feature of KDE that triggers an action whenever the mouse is pushed against a corner or side of the screen; the Grid action displays all the workspaces in a grid, similar to the screenshot above. This lets me use my mouse to switch workspaces by throwing it into the nearest corner and picking the workspace I want.
Back in the day, this used to be the worst feature of my setup for people unfamiliar with it... until I switched to the Colemak keyboard layout
A falling terminal. Currently, I use Yakuake for this; it lets me take my command-line shell to all the workspaces, and it's bound to the left-hand-only Ctrl-Alt-T shortcut for Ubuntu nostalgia. Having all my terminals available everywhere means I don't have to dedicate a workspace for them and I can
Auto-hide everything. I believe I picked that from a friend, who always has his toolbars and menus set to hide It saves on a bit of screen real estate, while still keeping those menus available with just a mouse flick.
Oh, and last; I do have a scrolling wallpaper that moves with the current workspace for extra eye-jingle, plus a docking application menu bar since it looked cool.
Kate (and, nano)
As a programmer, one of the main things I need to interact with is a text editor. Much has been written elsewhere on the merits and shortcomings of different editors; there are those that are chock-full of extensions that might help you write code better, there are those that have lots of keybindings to let you change code faster; as for me... all I've got in my toolbox editor-wise is syntax highlighting, decently-smart autocompletion, and a regex-based find/replace feature.
I've found that in... Kate: KDE's default2 text editor. Kate has syntax highlighting and good autocomplete support through language servers (a godsend compared to the IDE-heavy world that preceded language servers), and reasonable find/replace features. And, as a bonus, it has a list of project files on the side and a keybind to quickly navigate to a file by name, both of which I've put to good use.
Another feature of virtually all text-editors that I end up using a lot is holding down Ctrl to move by a whole word, along with the Home/End keys to jump to the start/end of a line. Combining either of those with Shift (or with backspace/delete) lets me quickly select and replace whole words or lines, without having to count them out character-by-character.
(Meanwhile, for editing files in a terminal, I've since defaulted to nano
. It is simple, has some syntax highlighting if configured, and all important keybindings are listed at the bottom. Vi-like editors are cool, but take more time to grasp, and... I haven't crossed that bridge yet.)
Fish shell
The other thing I get to spend a lot of time staring at is a terminal (which is, in my case, a drop-down terminal, as mentioned).
Almost everything in Linux can be automated through the liberal use of commands, and while commands aren't particularly hard to type in once you get the hang of them, some command-lines can get rather lengthy. And it's nice to have a library of such command lines.
For that, I use the Fish shell. I won't necessarily recommend it, as it's not fully POSIX-compliant (so things written for Fish won't work on other shells and vice versa), but the main feature I love about it is that I can just start typing up a command and it would suggest a completion from history that I can just use if I want to. The other Fish feature I find amazing is that I can type up the path to a directory (like, dir/
or ~
) without a cd
in front, and it will directly navigate there. So.. just because of those two little quality-of-life features, I enjoy using Fish a lot more than other shells, overall.
(Another thing that I like about Fish is that it would expand echo $(echo -e "1\n2\n3")"a"
to 1a 2a 3a
. Try that on Bash—it expands to 1 2 3a
instead.)
I will have to dive more into command-line tricks I employ in a later article..
GIMP and Inkscape
A pair of tools I use a lot when I need to do anything with images are GIMP and Inkscape.
GIMP is an editor for raster images—images made out of pixels; things like PNGs and JPEGs. It has a ton of features, but what I typically end up using from it is Layers/Layer groups, Gradients, and Filters (especially Gaussian Blurs), and the venerable Curves tool for fixing up bad lighting. Also, the Brush tool (with Shift to quickly draw straight lines) as well as the Crop and Selection tools.
I used to use GIMP a lot more when I was younger... but these days, I often reach for Inkscape instead. It is a vector image editor for SVG images. Vector images can be zoomed-in infinitely without getting pixelated—which tends to please the perfectionist side of me. Inkscape also has a lot of snapping options that I reach for when making different kinds of tilings; it also supports a variety of ways to draw and modify SVG paths (shapes), all of which are quite useful. I'm still learning some of the features of Inkscape as I go, but it's safely embedded into my image creation workflows now.
Git
On to more practical matters, like project organization.
There's hardly a programmer out there that doesn't use some form of version control for their projects. And I'd say there isn't much wonder why! The utility of being able to always go back to a specific previous version of a project (say, a version before something was broken, or before a major rework, or perhaps a version that is currently used by someone else) is always useful—and for programming projects in particular, invaluable, since even small changes can sometimes spell the difference between "works great" and "completely broken".
There is quite a few version control systems in use these days (e.g., Hg or Pijul), but the most popular one is definitely Git. I picked Git up mostly around working on Godot, and these days, I can't make a code project without throwing it into Git along the way.
With even basic usage, Git already delivers most of what you might want for versioning text files: a system to store versions of your code and to see the changes (patches/diffs) between any two specific versions, as well as to share those versions with others. But with even slightly more advanced usage, you can do a lot to improve what the list of versions ends up looking like: you can split up versions (commits) into smaller parts, split off a version in a branch, and later decide if you want to merge it back into the main branch, or even go back in time to fix a problem in the original version it was introduced in—rather than layering an extra "fix-up" version on top.
Personally, I tend to use Git exclusively from the command line. My most used commands, outside of git commit
, have to be git add -p
for manually reviewing changes being added into the new version and git push -u origin $(git rev-parse --abbrev-ref HEAD)
for pushing the (correct) current branch to the remote repository. I'm also quite fond of git stash
and of git rebase -i
.
Bash scripts
And well... on the topic of project organization, another tool I've picked up over the years is tossing short shell scripts into the project's main directory. These would have short names like build.sh
or run.sh
and usually consist of just one or two commands I use to run said project—sort of like specifying commands in a project.json
file, except without depending on NPM for the particular project.
Usually, I don't include such scripts in Git if I'm working on a project with other people, since not everyone likes having 3-10 shell scripts in the project root. But, for projects I work on alone, I do include such scripts in Git. For example, the project repository for this website has a random new-article.sh
utility script solely to automate filling out the template I use for articles without me needing to copy it around.
For the most part, I write my utility shell scripts in Bash. It, like Fish, is also a shell programming language, tailored around describing how other programs should run. However, unlike Fish, it is much more widespread and stable, so I have less worry that an utility script written today would randomly break in a few years, plus I can share such scripts much more easily than I would share a Fish script.
So... what good's that toolbox?
My own toolbox is a bit nonstandard. Even for a programmer. The vast majority of people don't use Linux for their desktops—even the vast majority of programmers, I'd suspect. Also, many programmers would reach for more powerful text editors (whether in terms of extensions and features, or in terms of modal interfaces or scriptability), yet I enjoy just using the bare-minimum ones. And even among people that both use Linux and Kate, I'd doubt many of them also use a Fish shell but stick to Bash scripts.
And that is, just the beginning. I've described just the core parts of what my toolbox holds, and I haven't gotten to talk about specific programming languages, specific CLI tools, or even specific websites I often reaching for. It is honestly a lot that goes into a toolbox! And, so hard to express every single detail of how some person—any person—chooses to use a computer.
But, for now, I hope you enjoy this writeup: I personally tend to benefit from learning about other people's workflows, since every so often I happen across about a new tool or feature that I can make better use of myself.
This has been my 5th post of #100DaysToOffload. Bit behind, busy week, but let's hope next one leaves more time to write. 😁
Perhaps, in part inspired by Joel's post on default apps?↩︎
There's also KWrite, but it and Kate share almost identical due to both using the same KTextPart engine.↩︎