Better Shell Scrollback with Timestamps

Last week I noticed a pattern in some of my shell workloads: run something in a shell, go change some code, run it again. And often I'm looking for some sort of change between runs.

One of the most common things that could change (which I may not always notice) is how long the thing took to run. You could solve this with a utility like time, but you have to remember that, and it also pollutes your shell history, obscuring the actual thing you were trying to run.

Another common workflow is comparing somewhat detailed log outputs for differences. A single shell scrollback buffer is TERRIBLE for this, because you can't compare things side-by-side. So I often use multiple tabs/buffers/windows. This introduces a new problem though: remembering which one you ran last! It sounds silly, but I may go heads down for hours and it's very easy to forget!

I solved both of these with a better shell configuration. I'm using nushell, but something similar should be achievable in most shells:

NOTE: An earlier version of this post had a different configuration. I later revised it so that everything goes in the right prompt. This is a bit cleaner, and solves another shell problem where commands overflow the scrollback buffer.

# Right prompt: start time and duration of the last command.
# The right prompt renders *after* the last command finishes,
# so (date now) is effectively when the command completed.
# Subtracting CMD_DURATION_MS gives the actual start time.
$env.PROMPT_COMMAND_RIGHT = {||
    let ms = ($env.CMD_DURATION_MS? | default "0" | into int)
    if $ms < 1 {
        ""
    } else {
        let duration = (($ms * 1_000_000) | into duration)
        let started = ((date now) - $duration | format date "%Y-%m-%dT%H:%M:%S%:z")
        $"@($started) took ($duration)"
    }
}
$env.TRANSIENT_PROMPT_COMMAND_RIGHT = null

Once you've made the edits, you can reload your config with exec nu. And now your scrollback is a log! Every entry has a start timestamp and a duration.

Posts from blogs I follow

Four levels of in-place initialization

IntroductionThe goal of in-place initialization is to enable the construction of types directly into a memory location without any additional moves or copies. When working with big types this can be more efficient and even prevent stack ove...

via Yosh Wuyts β€” Blog

Against Chat

The most prevalent interface of recent fame is undeniably the chat window. Today it feels ubiquitous, to the extent that almost all interactions gravitate toward a single indistinguishable blob. This seems due in large part to an assumpti...

via Max's Homepage

Generating a Neovim Reference Card with Nix

I started learning emacs the other day, and I happened to stumble upon this reference card, designed by Stephen Gildea: It’s beautiful (and GPLv3)! So naturally I wanted to make my own. My initial concern wa...

via Andrew Zah

Generated by openring-rs from my blogroll.