Tue. Oct 26th, 2021
Piping stdout and stderr to Preview — Erica Sadun

Some time ago, I wrote about how it was useful to redirect a man page to Preview. This allows you to keep the man page open, search and generally have a better user experience than struggling with more (or less) to browse the information provided.

man -t apropos | open -fa Preview

Recently, someone asked me about a more modern command-line interaction, specifically, commands that use --help or similar to provide your documentation. This information can also be opened in Preview.

So I put on my hat thoughtfully and got to work. The first command line utility I decided to work with was screencapture because I’ve been using it a lot these last few days. However, it appears that Apple has failed to build a real help system beyond man. It was a bad choice to try to use to render, but I decided to keep working because I wanted to be able to pipe both stdoutand stderr to view.

What I made up looked something like this, all in one line, of course:

bash -c "screencapture -? &> 
    $TMPDIR/previewrendertext.txt; 
    /usr/sbin/cupsfilter -i text/plain 
        -D $TMPDIR/previewrendertext.txt 
        2> /dev/null | 
    open -fa Preview"

It all depends on cupsfilter, which can convert a text file into a printable format, which happens to be readable by Preview as a PDF.

I’m doing a bit of conglomeration, joining stderr and stdout streams using &> and save them on my mac $TMPDIR. This file is cleaned by -D option of cupsfilter.

I’m also removing the incessant debug messages from cupsfilter redirecting them to /dev/null before opening the print output in preview.

Note that I’m still using tcsh/zsh about bash on my main system, so that certainly affects things. Since I needed some of the bash nuance, I decided to run everything squeezed as a single -c command. (I’m sure if I spent enough time, I could do it all in csh but I really didn’t want to waste that time.)

As you can see in the previous image, an older utility intended for man the output doesn’t seem so pushed to the view via cupsfilter, especially with line lengths. There’s also no nice groffing and troffing ​​to make everything beautiful, just the way you get it man:

So how would this kludge work with a modern command line application like those produced using the Swift argument parser (https://github.com/apple/swift-argument-parser)? First, I created a utility that would allow me to run any command (well, as long as it was quoted correctly) without having to type in all the details each time I ran it:

#! /bin/bash

[email protected] &> $TMPDIR/previewrendertext.txt ; /usr/sbin/cupsfilter -i text/plain -D $TMPDIR/previewrendertext.txt 2> /dev/null | open -fa Preview

This allowed me to call preview "now --help" to redirect the default help message from my now utility (https://github.com/erica/now) to view. Yeah, originally I just wanted to pipe stuff to it, but I couldn’t figure out how to get stderr and stdout piped together in a single stream, let alone convert them to a file format because cupsfilter neither knows nor makes pipes.

It’s very readable and well-formatted due to the automatic configuration that the Swift Argument Parser provides from my code, but it looks, you know, pretty simple.

So I went ahead and tried to see what would happen if I tried a little bit going through /usr/bin/groff -Tps -mandoc -c instead of using cupsfilter:

bash -c "now --help &> 
    $TMPDIR/previewrendertext.txt; 
    /usr/bin/groff -Tps -mandoc -c 
    $TMPDIR/previewrendertext.txt" | 
    open -fa preview

And it’s…very meh. I tried mandoc, mdoc, me, mm, ms and www formats. All came out the same and none of the SAP tabs really worked. I think it looks a lot more “manny” than direct printing, but the indentation is really buggy:

I decided to stop at this point, as there really is a time when additional effort just isn’t worth the investment anymore – so I could throw it out there and see if that was in anyone else’s interest.

Notify me.

Leave a Reply

Your email address will not be published. Required fields are marked *