Designing a right prompt

May 7, 2016

[Edit: the below is something I wrote when I was trying to figure out what I should implement in my fish shell. Then I spent about eight hours implementing it, and when I was done, I immediately found that there were things about it that I didn’t like the way they "felt", so I changed them and edited the article to match. But experience shows that if there were already things that I didn’t like before I tried them, there will probably be more things that I discover I don’t like as I use them. So maybe it’s best to consider this article less like a design guide and more like an exploration of the design space.]

Since I’ve started playing with the fish shell, I’ve started to mess around with my prompt so I can maintain the only feature I actually cared about from my bash configs, which is that it showed git status in the prompt. Because I’m vulnerable to nerd sniping, this made me start to think about what information I definitively wanted in my prompt and where (since fish offers a "right prompt" as well as the typical left one).

I found a bunch of examples online where people had customized their prompts to whatever they found appealing for whatever reason, but relatively little about what brought them to that design in the first place. What things did you put in what order in what locations and why? What things did you decide that you didn’t need and how does that affect your workflow?

This is a brief post about what my decisions were and why.

A prompt should balance three concerns:

  • Display important information.
  • Take up as little space as possible.
  • Be aesthetically appealing.

These concerns are in tension, because as you display more information, you take up more space, and as you condense things into a smaller space, you sacrifice aesthetics. I cared less about aesthetics than about space, so I decided I would try to keep my prompt to one line if possible, even if that meant an uglier prompt.

Which information is important? On most machines I use, the "default" prompt includes

  • my username
  • current hostname
  • current path
  • some kind of symbol, traditionally "$"

Sometimes tools like virtualenv will add a prefix to indicate what environment you’re in. I wanted to subsume that too.

I knew I wanted to add

  • git status when it makes sense — what branch, whether the working directory is clean, and if we’re in the middle of a some operation like merge or rebase. I do most of my git stuff from magit, but sometimes I do one-off commands from the shell.
  • a "warning" that would indicate if the last command took too long (inspired by fish’s built-in $CMD_DURATION variable)
  • a "warning" that would indicate if the last command failed

I decided that in order to maximize space, I was going to remove my username from the prompt — I usually only have one account on any given machine, and I use sudo when I need to execute commands as other users. I also didn’t need a symbol if there was some other clear way to distinguish where my prompt began (for example, if it were a different color, or if some other part of the prompt were distinctive).

Which things would go on the left, and which on the right? As far as I can tell, there are two factors that go into this decision:

  • Left prompts are more visible, since you look at what you type and your typing begins just after the prompt. Because of this, it makes sense to put things in the right prompt that you need but only occasionally.
  • Right prompts go away when your cursor gets to them, which frees up more space at the cost of dropping information. Because of this, it makes sense to put things in the left prompt that you may want to refer back to in a few lines.

I noticed that commands that change the git branch are usually pretty short, so I could put the git branch on the right and if I didn’t see it, I could assume it hadn’t changed.

On the other hand, if I were in the middle of a merge or rebase, I wanted that to be obvious, since (unlike most git operations) cleaning up after a mistake during an interrupted merge or rebase can be a pain. I thought the "command failed" warning could be condensed to a single character, and I thought I’d want to know every time a command failed, so that would go on the left too. And because I wanted last command status on the left, I should put $CMD_DURATION on the left too for consistency.

That left the hostname and path. My normal workflow involves opening a bunch of tabs, one for each "location", and changing rarely. As a result, during the normal course of my day, I usually know "where I am", and in modern shells, I can just glance at the title bar if I forget where a tab is. But both hostname and path are super useful to refer back to during a transcript or especially when something goes wrong. For this reason I thought I would experiment with removing hostname and path from my prompt entirely but emphasizing changes to those values so that they would show up more obviously in a transcript. fish doesn’t provide a hook for this, but it’s easy enough to simulate by tracking state in a global variable and checking if it changed. I wasn’t quite ready to get rid of it entirely, but for now, the cwd is in the right prompt. We’ll see how that goes.

It took me a while to discover that fish ships with extensive support for putting git in your prompt (with the builtin __fish_git_prompt). It’s not quite as flexible as you might want, but it does have a bunch of sample code that might be useful if you want some of its power.

You can see what I ended up with at fish_prompt, fish_right_prompt, and fish_title. Hope this helps someone else designing their prompt!

Comments Off on Designing a right prompt

Sourdough Bread

April 28, 2016

I lost this link earlier today, so here it is in case I need to find it again: Sourdough Bread: How To Begin.

Comments Off on Sourdough Bread

The fish shell

April 7, 2016

Continuing in the vein of my previous posts about changes I’m making to my development setup, this week I have been looking at shells. Somewhere once upon a time I encountered the idea that cool kids don’t use bash, and the commonly-cited alternatives are zsh and fish. A thread on Reddit pointed out a few of the compelling advantages of zsh over bash, and Ars Technica has a fairly old article detailing some of the ideas behind fish.

Some people complain about fish’s not supporting !! and related syntax like !$, but I’ve always found the expansion of ! problematic (when e.g. writing commit messages) and I prefer to just use interactive editing of commands from my history, or Alt-. to retrieve the last word in a previous command. (fish supports both quite well.)

Some features that I really like about fish so far are:

  • Tab completion. I think I must have tried zsh once a long time ago because I have some sort of vestigal memory of trying to tab-complete some filename and hating it. Specifically, I remember hitting Tab a few times (which is deeply ingrained in my muscle memory from years of using bash), and zsh immediately inserting something into my command line, with my only option to keep pressing Tab until I got to what I wanted. (I believe this is called menu completion in the literature.) I felt this was too aggressive; if I wanted to refine the filename a bit, or if I saw that I had entered the wrong directory, I had to erase what the shell had just injected. fish’s tab completion is like all the best parts of this mechanism, but better. It isn’t adequately covered in the documentation, but this Stack Overflow post does a good job detailing its behavior. Basically, you can cancel the tab completion using Escape, and you can refine the search by typing stuff even once you are in "menu" mode, sort of like an ido/swiper sort of thing. Very slick.
  • If a command prints some output that doesn’t end in a newline before you get to a prompt, fish puts out a cute ⏎ symbol and inserts a newline. Your prompt always starts on a new line, but you get a clear indication that what you see isn’t exactly what you got.
  • Ctrl-K and Ctrl-Y on the fish command line interoperate seamlessly with my windowing system’s clipboard.
  • I’ve never been super into pushd/popd, but fish has prevd and nextd which seem pretty nice.

Lots of people online recommend oh-my-zsh or zprezto, but it mostly seems like the things zsh offers (even with these packages) aren’t incredibly amazing. Maybe there’s some draw for die-hards, but there’s a lot of overhead involved in learning these packages, setting them up, and maintaining them. By comparison, fish has hardly any configuration available at all, so hopefully you like how it works, because if you don’t, you can’t change it.

In general, the dichotomy between zsh and fish is between the incredibly flexible Swiss-Army-knife all-singing-all-dancing tool with a gazillion options, and the beautifully crafted tool with only one, extremely-carefully-thought out option. zsh is KDE and fish is GNOME. Or, zsh is Perl, and fish is Python. I’m sure you can come up with some other analogies.

I’m still getting my prompt and favorite functions set up, but a few commands I’ve found useful:

  • type [commandname] lets you see what kind of command something is, and if it’s a shell function, see its definition. Apparently this is common to even bash, but I had never used it before.
  • vared lets you interactively edit a variable. zsh has this too; fish also has funced for editing functions.

A couple things I’m annoyed about:

  • The fish web page compares fish’s autocomplete behavior to a browser’s, but there’s no way to tell fish to not record history for a shell session, analogous to a browser’s "private browsing" mode.
  • In both fish and zsh, array indices start at 1, not 0 as you might be used to.
  • fish’s readline doesn’t support Control-_ for undo, and maybe doesn’t support undo at all.
Comments Off on The fish shell

All the disabled commands in Emacs

March 13, 2016

I’m still cleaning up my emacs configuration. I stumbled across the configuration I did to enable the narrow-to-region command, and figuring that the "disabled" commands are likely to be pretty interesting, wondered "What other commands are ‘disabled’?" There’s no list that I could find online, but you can find out for yourself with a little lisp:

  (lambda (x)
    (when (get x 'disabled)
      (message "disabled: %s" x))))

On my machine, this produces the list:

disabled: erase-buffer
disabled: set-goal-column
disabled: narrow-to-page
disabled: upcase-region
disabled: narrow-to-defun
disabled: scroll-left
disabled: Info-edit
disabled: dired-find-alternate-file
disabled: downcase-region

… as well as, of course, narrow-to-region, which I de-disabled myself.

Comments Off on All the disabled commands in Emacs

org-mode and use-package

March 12, 2016

I just spent a bunch of time converting my old, crufty, el-get/elhome dot-emacs.d files to the new hotness, use-package. I spent more time than I’d like to admit to get org-mode to work correctly. I needed to both remove it from the load-path as well as deleting org from the package--builtins list. The full solution is available here if you want to use it.

Comments Off on org-mode and use-package

Horsetail Firefall

August 10, 2013

Via Suzanne, like three years ago. Some pictures of the Horsetail Firefall.

Comments Off on Horsetail Firefall

Arabic: A language with too many armies and navies?

June 24, 2013

Seen on Language Log: a piece in the Economist about Arabic:

Today, the Arab world is sometimes compared to medieval Europe, when classical Latin was still the only "real" language most people wrote and studied in—but "Latin" in the mouths of its speakers had become early French, Spanish, Portuguese and so on. Today, we recognize that French and Portuguese are different languages—but Arabs are not often sure (and are sometimes at odds) about how to describe "Arabic" today. The plain fact is that a rural Moroccan and a rural Iraqi cannot have a conversation and reliably understand each other. An urban Algerian and an urban Jordanian would struggle to speak to each other, but would usually find ways to cope, with a heavy dose of formal standard Arabic used to smooth out misunderstandings. They will sometimes use well-known dialects, especially Egyptian (spread through television and radio), to fill in gaps.

Short read, well worth your time. Also related: the ongoing discussion of whether Chinese is a language with dialects, or a language group with languages.

Comments Off on Arabic: A language with too many armies and navies?

Cancer deaths have been falling since 1990

May 9, 2013

Via Suzanne — on the meme of cancer, if such a thing exists. Boing boing has a short blurb about cancer.

A new study suggests that cancer deaths for people under age 75 have been on the decline since 1990 and are now at levels lower than when the War on Cancer began in 1971. But rather than amazing new treatments, the big key seems to be prevention—both through an increase in screening, and a decrease in risky behaviors, especially smoking.

Comments Off on Cancer deaths have been falling since 1990

Half-Cocked? Hermaphrochickens Challenge Gender Determination

April 15, 2013

Via Suzanne, who writes, "Shared for title". Wired on how chicken gender assignment works:

Unlike mammals, it’s not hormones that dictate a chicken’s sex. It’s a fundamental property of the cells themselves. But this only became apparent when biologists investigated several odd chickens that were half male and half female, as if a line were drawn down the center of their bodies.

Comments Off on Half-Cocked? Hermaphrochickens Challenge Gender Determination

Lactation Assault

March 19, 2013

Lord, I read weird sites. This one is from JWZ: Lactation Assault.

After Toni Tramel, 31, was arrested last Thursday for public intoxication, […] Tramel "took off her bra, grabbed her breast and squirted breast milk, hitting me in the face and neck region," reported Brown. Tramel attempted a second lactation assault, "but was unsuccessful," added Brown. […] As for Brown, a jail press release noted that the officer was successfully able to "clean the bio-hazard off her."

Comments Off on Lactation Assault