4

My .psqlrc has following options

\setenv LESS '-iMSx4 -FXR'
\setenv PAGER 'less'
\pset pager always

and psql output which I want to be colored is

 {                                                                    +
    \x1B[35m"\x1B[0m\x1B[35mr\x1B[0m\x1B[35m"\x1B[0m: [               +
       \x1B[1m\x1B[92m"\x1B[0m\x1B[32m1\x1B[0m\x1B[1m\x1B[92m"\x1B[0m,+
       \x1B[1m\x1B[92m"\x1B[0m\x1B[32m2\x1B[0m\x1B[1m\x1B[92m"\x1B[0m,+
       \x1B[1m\x1B[92m"\x1B[0m\x1B[32m3\x1B[0m\x1B[1m\x1B[92m"\x1B[0m,+
       \x1B[1m\x1B[92m"\x1B[0m\x1B[32m4\x1B[0m\x1B[1m\x1B[92m"\x1B[0m,+
       \x1B[1m\x1B[92m"\x1B[0m\x1B[32m5\x1B[0m\x1B[1m\x1B[92m"\x1B[0m,+
       \x1B[1m\x1B[92m"\x1B[0m\x1B[32m6\x1B[0m\x1B[1m\x1B[92m"\x1B[0m,+
       \x1B[1m\x1B[92m"\x1B[0m\x1B[32m7\x1B[0m\x1B[1m\x1B[92m"\x1B[0m,+
       \x1B[1m\x1B[92m"\x1B[0m\x1B[32m8\x1B[0m\x1B[1m\x1B[92m"\x1B[0m +
    ]                                                                 +
 }

Is there a way to make pager aware of \x1B ansi sequences, or to tell psql not to convert them to hexadecimal representations when displaying?

Output should look like,

enter image description here

xhienne
  • 5,738
  • 1
  • 15
  • 34
mpapec
  • 50,217
  • 8
  • 67
  • 127

2 Answers2

3

The less pager can be told to filter its input files using the LESSOPEN environment variable.

For your case, that could be the name of a script which changes all of \x1B to the ASCII escape character, e.g.,

sed -e 's/\x1B/^[/'

(where the ^[ is a literal control[ character: using controlV when inserting with a text editor helps).

Further reading:

Per comment: if psql calls the pager via a pipe, bypassing LESSOPEN (which works given a file), you should set your pager to a script which does the combination of filtering and paging, e.g., a script something like

#!/bin/sh
perl -pe "s|\\\(x..)|chr(hex(\$1))|ge" | less -iMSx4 -FXR

since perl works from a pipe if no filenames are given.

EDIT:

Solution without external script using psql only,

\setenv LESS '-iMSx4 -FXR'
\setenv PAGER 'perl -pe \'s|\\\\(x..)|chr(hex($1))|ge\' | less'
Community
  • 1
  • 1
Thomas Dickey
  • 51,086
  • 7
  • 70
  • 105
  • Tnx, this works for me `export LESSOPEN='|perl -pe "s|\\\(x..)|chr(hex(\$1))|ge" %s'` – mpapec Nov 23 '15 at 11:58
  • Unfortunately it works only under shell, but not when using `psql`. – mpapec Nov 23 '15 at 12:28
  • If you put the command into a script, you can bypass problems with escaping and quoting. – Thomas Dickey Nov 23 '15 at 23:45
  • It's not problem with escaping as psql invokes `less` via pipe, and I've noticed that LESSOPEN doesn't work in such case, ie. `cat ansi_file.txt | less -r` while `less -r ansi_file.txt` works as expected. – mpapec Nov 24 '15 at 09:06
3

An "all-in-one" psql solution:

\o | sed -r 's/\\x1B\[([0-9]+)m/\x1B[\1m/g' | less -R

That's it --- no other psql or shell commands required.

How It Works

  • \o     <===   Gives us direct control of stdout.
  • | sed -r 's/\\x1B\[([0-9]+)m/\x1B[\1m/g'     <===   We re-print all the escape sequences exactly as they were, but now interpreted as themselves and not as literals.
  • | less -R     <===   We hand the result over to less(1) explicitly (psql isn't going to do it for us, because we took over control of stdout!). The options to be given to less(1) are up to you; as long as they include -R (or -r), colorization will happen.

Works for output of both SELECTs and of \echo meta-commands.