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

Capture Clauses as Effects

IntroductionIn my post on Hoisting Expressions I discussed the move($expr) feature and how it works much like an inverse of the defer feature many languages have. Instead of creating expressions which run after the scope ends, move($expr) r...

via Yosh Wuyts — Blog

Against Chat

The most prevalent interface of recent fame is undeniably the chat window. Today it feels ubiquitous, almost as if all interactions gravitate into a single indistinguishable blob. There may be many different reasons for this, some good, ...

via Max's Homepage

Generated by openring-rs from my blogroll.