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

Why fsyncing a File Isn't Safe Enough

Recently I learnt something interesting about writing files to disk. Something that connects my first ever low-level database PR with the reason you can’t pull a USB disk out of your laptop without ejecting it first. As you may know, when y...

via Kris Jenkins' Blog

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

Generated by openring-rs from my blogroll.