rofi: Overview and Installation

This is the first in a series of several posts on how to do way more than you really need to with rofi. It's a neat little tool that does so many cool things. I don't have a set number of posts, and I don't have a set goal. I just want to share something I find useful.

Assumptions

I'm running Fedora 27. Most of the instructions are based on that OS. This will translate fairly well to other RHEL derivatives. The Debian ecosystem should also work fairly well, albeit with totally different package names. This probably won't work at all on Windows, and I have no intention of fixing that.

Code

Overview

rofi makes it really easy to do things via simple shortcuts. It's super useful if you're trying to up your nerd cred, streamline your workflow, beef up i3, or make Linux that much more pleasant to run.

Rather than make my own shoddy feature list, I'm just going to link the official docs, whose screenshots are already very pretty. rofi can, among other things, do this stuff:

Installation

Instructions were mostly sourced from the official docs. I tweaked a couple of things and made sure everything worked easily on Fedora.

I tested installation from start to finish in a fresh Vagrant box.

$ vagrant init fedora/27-cloud-base

I'm (mostly) certain everything will work there. Unless you configure the box to handle or pass off X events, you won't actually be able to view rofi via Vagrant, but you can ensure the build process works as intended.

Dependencies

I make heavy use of bash's brace expansion. If you're not using bash, I'm sorry. To make things easier, I'll turn on debug mode.

Debuggable

If you're fighting issues, or want to see how things work, you can also build rofi with some debugging options. You can either replace the existing rofi or you can install them side-by-side using the --program-suffix installation option (which is what I do below). More information can be found in the official debugging docs

If you're missing some of these options, you'll need to wade through the configure log and figure out which libraries are missing.

I'd be lying if I said I fully understand the debug build. I had to first make without debug symbols, then remake with debug symbols. Without the initial make, a couple of important headers aren't built, and I wasn't able to trace how to make just those files (rofi has a fairly involved build process and I'm weak at best with the GNU build system).

I used Python's APIs for directory manipulation, which means you'll have to run it as the user that owns the source and build directories. sudo is required for the default /opt/rofi location. This means the whole script is run as root. For example,

defclone_repo(dry_run=False):"""Clones the repo"""commands=[['git','clone','https://github.com/DaveDavenport/rofi','--recursive','.']]run_commands(commands,dry_run)

defupdate_existing_repo(dry_run=False):"""Attempts to update. Falls back to clone if repo DNE"""try:call(['git','status'])exceptCalledProcessErroraserror:ifERROR_NOT_A_REPO==error.returncode:returnclone_repo(dry_run)else:raisecommands=[['git','stash'],['git','reset','--hard'],['git','pull'],['git','submodule','init'],['git','submodule','update'],]returnrun_commands(commands,dry_run)

defcli():"""Bootstraps the script"""options=parse_argv()setattr(options,'configure',join(options.source,'configure'))install_dependencies(options)prep_source_directory(options)refresh_source(options)restore_tooling(options)build_and_install(options)review_commands(options)sys_exit(0)