PSPG(1)
๐ pspg(1) โ the pspg manual, bestie edition ๐
okay so this is the manual page for pspg, from the pspg manual. yes the title is literally just the name twice, don't ask. anyway. sit down, grab a strawberry ๐, we're learning a pager.
โจ NAME โจ
pspg โ Postgres Pager. that's it, that's the name. it's giving "simple but iconic" ๐
๐ธ DESCRIPTION ๐ธ
so here's the lore: everybody who uses psql also uses the less pager. and like, less works well, no shade, but it has zero special support for tabular data. none. it looks at a table and just sees text. tragic honestly ๐ญ
the author found a few projects that tried to fix this, but none of them was good enough for this purpose. so obviously the only logical move was to write a small specialized pager to use as a psql pager. main character energy fr fr ๐
and this pager can be used from these command line clients too, not just psql:
mysqlsqlitepgclihttps://github.com/dbcli/pgcli/monetdbTrino(formerly Presto SQL) https://trino.io/usqlhttps://github.com/xo/usql/sqlclhttps://github.com/okbob/pspg/#sqlcl (for oracle)nushellhttps://www.nushell.sh/
like, the range?? we love a versatile icon ๐
๐ฏ Main target
so what is this pager actually about? bestie. let me tell you.
- ability to freeze the first few rows, or first few columns
- ability to sort data by the specified numeric column
- ability to use fancy themes - like
mcvieworFoxPro- http://okbob.blogspot.com/2019/12/pspg-themes-what-you-use-it.html - mouse is supported and used
- ability to copy a selected range to the clipboard
frozen headers AND clipboard copy AND cute themes? she ate and left no crumbs ๐ฅ
๐ง Installation and basic configuration
the pspg can be simply installed from Debian (Ubuntu) repositories. RedHat (Fedora) repositories contains pspg too, so nobody's left out:
# Debian (Ubuntu)
sudo apt-get install pspg
# RedHat (Fedora)
sudo dnf install pspg
basic configuration is very simple - just set the system environment variable PSQL_PAGER:
export PSQL_PAGER='pspg'
or, if you want some common options (-b means blackwhite theme, -X preserve content after exit):
export PSQL_PAGER='pspg -X -b'
โ ๏ธ Attention: options used in command line has higher priority than options specified in configuration file (~/.pspgconf). so like, the command line is the boss here. periodt.
native installation on MS Windows is not supported, but pspg works well inside wsl2. inside wsl2 environment, the installation is same like on used Linux system. so basically: windows girlies, go through wsl2, it's fine ๐ซถ
installation on macOS/homebrew is simple by brew install pspg.
๐ฌ Video presentation
https://www.youtube.com/watch?v=JyxuEkoYDQk
like, actual moving pictures of it working. go watch, i'll wait ๐
๐ธ Screenshots
(yes bestie, there are screenshots on the real page โ this is the part where they live ๐ผ๏ธโจ)
๐ Options
okay this next bit is the whole --help output, so buckle up. here's what it looks like when you run it:
[pavel@localhost ~]$ pspg --help
pspg is a Unix pager designed for table browsing.
and the usage is literally:
pspg [OPTION] [file]
now the actual options, organized cute so you don't get lost ๐
โจ General options
--aboutโ about authors (the lore, the credits, the icons behind the icon)--helpโ show this help-V,--versionโ show version--infoโ show info about libraries and system--direct-colorโ force direct-color terminal mode-f,--file=FILEโ open file-F,--quit-if-one-screenโ quit if content is one screen--clipboard-app=NUMโ specify app used by copy to clipboard (1, 2, 3, 4)--esc-delay=NUMโ specify escape delay in ms (-1 inf, 0 not used, )--interactiveโ force interactive mode--ignore_file_suffixโ don't try to deduce format from file suffix--niโ not interactive mode (only for csv and query)--no-watch-fileโ don't watch inotify event of file--no-mouseโ don't use own mouse handling--no-progressive-loadโ don't use progressive data load--no-sigint-search-resetโ without reset searching on sigint (CTRL C)--no-sleepโ without waits against flickering--no_xterm_mouse_modeโ don't use optional xterm mouse mode--only-for-tablesโ use std pager when content is not table--on-sigint-exitโ exit on sigint(CTRL C or Escape)--pgcli-fixโ try to fix some pgcli related issues--querystreamโ read queries from stream forever--quit-on-f3โ exit on F3 like mc viewers--rr=ROWNUMโ rows reserved for specific purposes--streamโ read input forever-X,--reprint-on-exitโ preserve content after exit
๐จ Output format options
-a,--asciiโ force ascii-b,--blackwhiteโ black-white style-s,--style=Nโ set color style number (0..22)--bold-labelsโ row, column labels use bold font--bold-cursorโ cursor use bold font--borderโ type of borders (0..2)--double-headerโ header separator uses double lines--force-uniborderโ replace ascii borders by unicode borders--highlight-odd-recโ highlights odd records (when it is supported by style)--hide-header-lineโ hides header line (between column names and data)--ignore-short-rowsโ rows with wrong column numbers are ignored--null=STRINGโ STRING used instead NULL
๐ Searching options
-g --hlite-search,-G --HILITE-SEARCHโ don't highlight lines for searches-i --ignore-caseโ ignore case in searches that do not contain uppercase-I --IGNORE-CASEโ ignore case in all searches
๐ฑ๏ธ Interface options:
-c,--freezecols=Nโ freeze N columns (0..9)--less-status-barโ status bar like less pager--line-numbersโ show line number column--menu-alwaysโ show top bar menu every time--no-bars,--no-commandbar,--no-topbarโ don't show bottom, top bar or both--no-cursorโ row cursor will be hidden--no-last-row-searchโ don't use the last pattern when starting a new search--no-scrollbarโ don't show scrollbar--no-soundโ don't use beep when scroll is not possible--tabular-cursorโ cursor is visible only when data has table format--vertical-cursorโ show vertical column cursor
๐ฅ Input format options:
--csvโ input stream has csv format--csv-separatorโ char used as field separator--csv-header [on/off]โ specify header line usage--skip-columns-like="SPACE SEPARATED STRING LIST"โ columns with substr in name are ignored--csv-trim-width=NUMโ trim value after NUM chars--csv-trim-rows=NUMโ trim value after NUM rows--tsvโ input stream has tsv format
๐ช On exit options:
--on-exit-resetโ sends reset terminal sequence"\33c"--on-exit-cleanโ sends clean terminal sequence"\033[2J"--on-exit-erase-lineโ sends erase line terminal sequence"\33[2K\r"--on-exit-sgr0โ sends sgr0 terminal sequence"\033[0;10m"
๐ Watch mode options:
-q,--query=QUERYโ execute query-w,--watch timeโ the query (or read file) is repeated every time (sec)
๐ Connection options:
-d,--dbname=DBNAMEโ database name-h,--host=HOSTNAMEโ database server host (default:"local socket")-p,--port=PORTโ database server port (default:"5432")-U,--username=USERNAMEโ database user name-W,--passwordโ force password prompt
๐ Debug options:
--log=FILEโ log debug info to file--wait=NUMโ wait NUM seconds to allow attach from a debugger
pspg shares a lot of key commands with the less pager or the vi editor. so if you already know those, you're lowkey already home ๐ โจ
options can also be passed within the PSPG environment variable. and here's the processing order, listen up because this matters: configuration file is processed first. options from the PSPG variable are processed afterwards step and command line options are processed at the end. one option can be processed multiple times, and the last value wins. so like, last one in wins the crown ๐
๐ Environment variables
the original page puts these in a cute little table, but we're doing bullets because we're built different:
PSPGโ can hold same options like command linePSPG_CONFโ path to configuration filePSPG_HISTORYโ path to filepspg's readline history file
๐ Example of config file
the default path of config file is ~/.pspgconf.
and heads up bestie: the fields names can be different than from related command line options. so don't come for me when they don't match, that's just how it is:
ascii_menu = false
bold_labels = false
bold_cursor = false
ignore_case = false
ignore_lower_case = false
no_cursor = false
no_sound = false
no_mouse = false
less_status_bar = false
no_highlight_search = false
no_highlight_lines = false
force_uniborder = false
show_rownum = false
without_commandbar = false
without_topbar = false
vertical_cursor = false
on_sigint_exit = false
no_sigint_search_reset = false
double_header = false
quit_on_f3 = false
pgcli_fix = false
xterm_mouse_mode = true
show_scrollbar = true
menu_always = false
empty_string_is_null = true
last_row_search = true
progressive_load_mode = true
highlight_odd_rec = false
hide_header_line = false
on_exit_reset = false
on_exit_clean = false
on_exit_erase_line = false
on_exit_sgr0 = false
direct_color = false
theme = 16
border_type = 2
default_clipboard_format = 0
clipboard_app = 0
hist_size = 500
esc_delay = -1
copy that whole block into ~/.pspgconf and you're so set ๐
โจ
(part 1 done bestie, more incoming ๐ฆ)
โจ Themes โจ
okay so pspg literally ships with a whole built-in theme menu, and the codes are numbered 0 through 23. no cap, here's every single one with the exact names so you can match them up ๐
0โ black & white1โ Midnight Commander like2โ FoxPro like3โ Pdmenu like4โ White theme5โ Mutt like6โ PCFand like7โ Green theme8โ Blue theme9โ Word Perfect like10โ Low contrast blue theme11โ Dark cyan/black mode12โ Paradox like13โ dBase IV retro style14โ dBase IV retro style (Magenta labels)15โ Red white theme16โ Simple theme17โ Solarized dark theme18โ Solarized light theme19โ Gruvbox light theme20โ Tao Light theme21โ FlatWhite theme22โ Relational pipes theme23โ Paper Color theme
see http://okbob.blogspot.cz/2017/07/i-hope-so-every-who-uses-psql-uses-less.html
๐ Custom themes ๐
you can customize over the base and menu templates while referencing the built-in themes. save your custom theme file in the directory with pspg configuration, and name it .pspg_theme_xxx. select it with the command line option --custom-style=name or with the command \ctheme name. obsessed ๐ซถ
here's an example of a custom theme file (named .pspg_theme_mc2, and yes it can be activated by the command \ctheme mc2):
template = 1
template_menu = 3
background = black, white
data = black, white
label = black, white, italic, bold
border = #000000, white
footer = lightgray, white
cursor_data = blue, white, italic, bold, dim, reverse
cursor_border = blue, blue , italic, bold, dim, reverse
cursor_label = blue, white, italic, bold, dim, reverse
cursor_footer = blue, white, italic, bold, dim, reverse
cursor_bookmark = red, white, italic, bold, dim, reverse
cross_cursor = white, blue, italic, bold
cross_cursor_border = brightblue, blue
status_bar = black, lightgray
title = black, lightgray
scrollbar_arrows = black, white
scrollbar_background = lightgray, white
scrollbar_slider = white, gray
some keys can be marked with the symbol *, and those marked keys are used for odd records:
data* = black, lightgray
label* = black, lightgray, italic, bold
border* = #000000, lightgray
So like, template and template_menu are your safety nets bestie ๐ โ they set fallback values for any keys you didn't bother specifying in your custom theme. And template_menu specifically? That's currently the only way to customize how the F9 menu looks. That's it. That's the whole vibe. ๐
Here's every key you can theme, no gatekeeping:
backgroundโ the background color, the canvas of your whole aesthetic โจdataโ text in data cells (aka anything that's not a header and not a frozen column)borderโ the border color, the ~frame~ around things ๐ผ๏ธlabelโ text for labels (headers and frozen columns, iykyk)row_numberโ the line numbersrecord_numberโ (the manual literally leaves this one blank, so no tea to spill ๐)selected_areaโ (blank in the original too, bestie, I'm not making stuff up ๐)footerโ the results footer, i.e. the non-tabular bit like a rowcountcursor_dataโ text in the highlighted data cell (again: non-header, non-frozen-column)cursor_borderโ the border color when it's highlighted ๐cursor_labelโ the highlighted label text (header or frozen column)cursor_row_numberโ the highlighted line numberscursor_record_numberโ (also blank in the original, we love an empty cell ๐ธ)cursor_selected_areaโ (blank again, iconic ๐ )cursor_footerโ the highlighted results footer (non-tabular, e.g. rowcount)scrollbar_arrowsโ the scrollbar's up and down arrows โฌ๏ธโฌ๏ธscrollbar_backgroundโ the scrollbar's "empty" backgroundscrollbar_sliderโ the scrollbar slider sitting over that backgroundscrollbar_active_sliderโ the slider when it's grabbed by the mouse ๐ฑ๏ธtitleโ the results headline (you'll see it in thepsqldescribe commands)status_barโ the top query + cursor location infoprompt_barโ (blank in the original, keeping it 100 with you ๐ซถ)info_barโ info text, like"Not found"when you're searching and it's giving nothing ๐ญinput_barโ the input prompt and text (search, for example)
error_barโ the manual doesn't spell this one out, it's just listed with a blank description ๐bookmarkโ same deal, listed with no description attachedbookmark_borderโ also listed bare, no description givencursor_bookmarkโ bare again, no descriptioncross_cursorโ Highlighted cell at intersection of horizontal and vertical cursorscross_cursor_borderโ Borders at intersection of horizontal and vertical cursorsmatched_patternโ Search result match textmatched_pattern_nohlโ listed with no description, so that's all the manual gives us ๐ซถmatched_lineโ Line containing search resultmatched_line_borderโ Borders in search result linematched_pattern_cursorโ Highlighted search result match textmatched_line_vertical_cursorโ Vertically highlighted search result match textmatched_line_vertical_cursor_borderโ Borders of vertically highlighted cell with search result matcherrorโ blank description in the docs, bestie, that's literally all it says
Okay so about the actual colors ๐ โ the ANSI colors Black, Red, Green, Brown, Blue, Magenta, Cyan, LightGray, Gray, BrightRed, BrightGreen, Yellow, BrightBlue, BrightMagenta, BrightCyan, White, and Default will display as your terminal emulator configures them. Not as pspg decides, as your terminal decides. iykyk.
Alternatively โ and this is the fun part, bestie โ you can specify hex RGB values like #FF00FF. Custom colors, main character energy. ๐
Styles โจ are any combination of: bold, italic, underline, reverse, standout, dim. Mix and match, go off, stack 'em.
If the format of some key is not correct, then this row is ignored. Like, silently. It just doesn't apply. ๐
For debugging of custom theme it's good to start pspg with option --log. An information about broken definitions are stored in log file. So when your beautiful lil theme isn't doing what you want, that's your move โ fire up the log, read what broke, fix it. ๐
โจ๏ธ Keyboard commands โจ๏ธ
okay bestie, this is the full keybind rundown โ every single shortcut, no skipping, all the facts staying exactly where they belong ๐ โจ
0,1,2,3, ..,9โ freeze first N columns.KEY_UP,kโ navigate backward by one line.KEY_DOWN,jโ navigate forward by one line.KEY_LEFT,hโ scroll to left.KEY_RIGHT,lโ scroll to right.Ctrl+KEY_LEFTโ scroll one char left.Ctrl+KEY_RIGHTโ scroll one char right.Shift+KEY_LEFTโ scroll one column left.Shift+KEY_RIGHTโ scroll one column right.Ctrl+Home,gโ go to the start of file.Ctrl+End,Gโ go to the end of file.Alt+lโ go to line number.Hโ go to first line of current window.Mโ go to half of current window.Lโ go to end of current window.PPAGE,Ctrl+bโ backward one window.NPAGE,Ctrl+f,spaceโ forward one window.HOME,^โ go to begin of line, first column.END,$โ go to end of line, last column.Ctrl+eโ scroll a window down.Ctrl+yโ scroll a window up.Ctrl+dโ forward a half window.Ctrl+uโ backward a half window.sโ save content to file./โ search for a pattern which will take you to the next occurrence ๐?โ search for a pattern which will take you to the previous occurrence (same energy, opposite direction, we love a backtracking queen)nโ for next matchNโ for next match in reverse directioncโ column searchAlt+/โ search for a pattern inside selected areaAlt+?โ backward search for a pattern inside selected areaAlt+cโ switch (on, off) drawing line cursorAlt+mโ switch (on, off) own mouse handlerAlt+nโ switch (on, off) drawing line numbersAlt+v, double click on column header โ switch (on, off) drawing column cursorMouse button wheelโ scroll verticalAlt+Mouse button wheelโ scroll horizontalF9โ show menuq,F10,Esc 0โ quit (three whole ways to say goodbye, pick your fighter ๐ )Alt+qโ quit and print raw (unformatted) contentAlt+k,Alt+double clickโ switch bookmarkAlt+jโ go to next bookmarkAlt+iโ go to previous bookmarkAlt+oโ flush bookmarksaโ sort ascendentdโ sort descendentuโ unsorted (sorted in origin order)Spaceโ stop/continue in watch modeRโ Repaint screen and refresh input fileInsโ export row, column or cell to default target
Okay bestie, real talk for a sec: that last one, Ins? That's your export button and it lowkey does the most โ it can ship out a whole row, a whole column, or just a single cell, and it drops it onto the default target. So before you mash it, know what your target is set to, iykyk ๐ฏ
And yeah, Alt+q is the sneaky icon move ๐ซถ โ normal q / F10 / Esc 0 bails out, but Alt+q bails out and hands you the raw (unformatted) content on the way. Different vibe, different output, both valid.
shift+cursor up, downโ defines the row range ๐ฏ like you're drawing the boundaries of your lil selection kingdomCtrl+Shift+cursor left, rightโ defines the column range, so now you're boxing in columns too ๐ฆF3โ start/finish of selection rows, press it to open the row-selection era and press it again to close it โจShift+F3โ start/finish of selection block, same energy but for a whole block this time ๐งฑCtrl+drag mouseโ defines rows selection, and if you do it on a column header it defines column selection instead ๐ฑ๏ธ lowkey iconic how one gesture does two jobsCtrl+oโ shows the primary screen, then press any key to return to the pager again ๐ yes literally any key, it's giving "no thoughts just vibes"%,Ctrl+aโ select all ๐ the "I want everything" button, no notes
๐ซถ BACKSLASH COMMANDS ๐ซถ
okay bestie, these are the little backslash spells you can type at the pager. every single one is here, no skips, no cap:
\Nโ go to line number\+Nโ go toNlines forward\-Nโ go toNlines backward\N+โ go to line number\N-โ go to line number from end\theme Nโ set theme number\copy [all\|selected] [nullstr "str"] [csv\|tsv\|insert\|text\|pipesep\|sqlvalues]โ copy data to clipboard\save [all\|selected] [nullstr "str"] [csv\|tsv\|insert\|text\|pipesep\|sqlvalues]โ copy data to clipboard\order [N\|column name]โ sort by column\orderd [N\|column name]โ desc sort by column\sort [N\|column name]โ sort by column\sortd [N\|column name]โ desc sort by column\dsort [N\|column name]โ desc sort by column (alias)\rsort [N\|column name]โ desc sort by column (alias)\asc [N\|column name]โ sort by column (alias)\desc [N\|column name]โ desc sort by column (alias)\search [back] [selected] [column name] [string\|"string"]โ search string in data
The output can be redirected to any command when the name starts with pipe symbol:
\copy csv | less
๐ ENDING ๐
The pager can be ended by pressing keys q or F10 or Esc 0. With option --on-sigint-exit then the pager is closed by pressing keys Ctrl+c or Esc Esc.
๐ฆ USE Escape, key INSTEAD Alt + key ๐ฆ
pspg supports a possibility to use a sequence of keys Esc, key instead of an Alt+key combination. The interval between pressing Esc and key is limited by interval specified by option esc-delay or by configuration's option esc_delay. This is max delay time in ms. After this interval, the single pressing Esc is interpreted as Escape. -1 means unlimited, 0 disables this feature.
๐ธ COLUMN SEARCH ๐ธ
Column search is case insensitive every time. Searched column is marked by vertical cursor. Last non empty string searching pattern is used when current searching pattern is empty string. Searching is starting after visible vertical column or on first visible not freezed columns (after some horizontal scrolling) or on first column. After last column searching starts from first again.
๐ EXPORT & CLIPBOARD ๐
For clipboard support the clipboard application should be installed: 1. wl-clipboard (Wayland), 1. xclip (xwindows), 3. pbcopy (MacOS) or 4. clip.exe (WSL2).
pspg try to translate unicode symbol โ
to NULL every time. If you don't use special setting by \pset null ..., then psql displays empty string instead NULL. pspg hasn't any special detection (in export routines) for this case. You should to check and enable or disable menu item Empty string is NULL.
pspg has automatic detection of clipboard application. Unfortunately, this detection should not to work for same cases. You can specify the application by specify number (1,2,3,4) to --clipboard-app option.
Formats make a difference! pspg copies records in CSV format by default, which uses comma separators and trims initial and trailing whitespace. Use "formatted text" to copy query output exactly, or choose one of the other available options.
๐ STATUS LINE DESCRIPTION ๐
V: [d/d d..d]โ vertical cursor: (column number)/(columns) (char positions from) .. (char positions to)FC: dโ freezed columns length in charsC: d..d/dโ unfreezed visible data in chars (from .. to)/(total)L:[d + d d/d]โ lines (number of first visible line) + (number of line of display), (current line)/(lines)d%โ percent of already displayed data
๐ Usage as csv viewer
okay so real talk โ pspg lowkey slays as a csv viewer too, and it plays so nice with miller (http://johnkerl.org/miller/doc/index.html). Bestie combo:
mlr --icsv --opprint --barred put '' obce.csv | pspg --force-uniborder
โจ New version has integrated csv support โ just use the --csv option and you're literally done.
It can also be integrated into mc ๐
:
- copy the file from
/etc/mc/mc.extto your~/.config/mcdirectory - insert this in there:
##csv
regex/\.csv
View=pspg -f %f --csv
- restart
mc
๐ซ Known issues
- When you use pspg on Cygwin, some temporary freezing of scrolling was reported ๐ญ In this case, please, use an option
--no-sleep. I see slow scrolling (via scrollbar) inside konsole (KDE terminal). The option--no-sleephelps too.
๐ Usage in watch mode
The result of the query can be refreshed every n seconds โจ pspg remembers the cursor row, possible vertical cursor, possible ordering. The refreshing should be paused by pressing the space key โ and repeated pressing of this key enables refreshing again. Cute, right?
pspg uses the inotify API when it is available, and when the input file is changed, then pspg rereads the file immediately ๐ฅ That behaviour can be disabled by the option --no-watch-file or by specifying watch time with the option --watch.
๐ Streaming modes
pspg can read a continuous stream of tabular data from a pipe, named pipe or from a file (with an option --stream), or it can read a stream of queries from a pipe or from a file (with an option --querystream). In stream mode, only data in table format can be processed, because pspg uses an empty line as the separator between tables ๐
The query stream mode is a sequence of SQL statements separated by the char GS (Group separator โ 0x1D) on a separated line.
pavel@localhost ~]$ cat < /dev/pts/3 > ~/pipe
select 10
^]
select 20
^]
select *
from
pg_class
^]
๐ธ Recommended psql configuration
you should add this to your profile ๐ซถ:
#for Postgres 10 and older
export PAGER="pspg"
#for postgres 11 and newer
export PSQL_PAGER="pspg"
#or "\setenv PAGER pspg" to .psqlrc
and in .psqlrc:
\set QUIET 1
\pset linestyle unicode
\pset border 2
\pset null โ
\unset QUIET
some possible configuration:
-- Switch pagers with :x and :xx commands
\set x '\\setenv PAGER less'
\set xx '\\setenv PAGER \'pspg -bX --no-mouse\''
:xx
LC_CTYPE should be correct ๐ Mainly when you use unicode borders. ncurses doesn't display unicode borders (produced by psql) without a correct setting of this variable. It's possible to check the value 'C.UTF8'.
โ ๏ธ Attention
When you use the option --only-for-tables, then:
- set
PAGERtopspgandPSQL_PAGERtolessor - set
PAGERtolessandPSQL_PAGERtopspg
๐ฌ MySQL usage
MariaDB [sakila]> pager pspg -s 14 -X --force-uniborder --quit-if-one-screen
PAGER set to 'pspg -s 14 -X --force-uniborder --quit-if-one-screen'
MariaDB [sakila]> select now();
MariaDB [sakila]> select * from nicer_but_slower_film_list limit 100;
๐ชถ SQLite
The SQLite native client doesn't produce well-formatted output, but it can be forced to generate CSV format โ and that format is well readable for pspg ๐
sqlite3 -csv -header testdb.db 'select * from foo2' | pspg --csv --csv-header=on --double-header
๐ pgcli
pgcli (https://github.com/dbcli/pgcli/) needs the following configuration options (~/.config/pgcli/config):
pager = /usr/bin/pspg --csv --rr=2 --quit-if-one-screen --ignore-case --csv-header on --pgcli-fix
table_format = csv
Older versions of pgcli had very slow output in tabular format ๐ A workaround was using csv format. This should not be necessary on current versions, when the performance issue was fixed. The option --pgcli-fix fixed the import of partially broken csv format generated by pgcli. Modern versions of pgcli don't need csv format, and don't need the --pgcli-fix option.
pager = /usr/bin/pspg --rr=2 --quit-if-one-screen --ignore-case
๐งก sqlcl
As sqlcl doesn't currently support a pager option directly, you can either use a tool like qsh (https://github.com/muhmud/qsh) to work around this issue, or use the pspg.sql script (https://github.com/okbob/pspg/blob/master/scripts/sqlcl/pspg.sql) from this repo.
To use the script, start sqlcl as shown below (it's important to pass in the details of your current tty):
$ TTY=$(tty) sqlcl system/system @/path/to/pspg.sql
You can now have the results of a query sent to pspg like this:
SQL> pspg select * from user_tables;
๐ nushell
pspg supports the default table_mode: rounded and table_mode: heavy ๐
The conversion to csv can be used too:
sys | get cpu | to csv | pspg --csv
Note: footer_mode should be disabled.
nushell configuration:
$env.config.footer_mode = never
$env.config.table.header_on_separator = false
$env.config.ls.clickable_links = false
$env.config.table.mode = rounded
๐ฑ๏ธ Note โ mouse
pspg tries to use xterm mouse mode 1002, when the terminal and ncurses are not too antique. If there are problems with usage โ unwanted visual artefacts when you move with the mouse while some mouse button is pressed โ then 1. please, report the issue (please, attach the log file), 2. use the option --no-xterm-mouse-mode and pspg will not try to activate this mode ๐
๐ Note โ true color themes on KDE konsole terminal
On my Fedora this terminal doesn't correctly display true color themes ๐ญ The basic problem is in the default TERM setting, that is xterm-256color. Unfortunately, the konsole terminal is not fully compatible with xterm, and doesn't allow color changing. You can force direct colors by using the option --direct-color or by setting TERM=xterm-direct. The second option is the more correct setting of the TERM variable to konsole-256color. In this case pspg will map the true rgb colors to supported 256 colors โจ
๐ ๏ธ Note โ compilation issue
Some linker issues can be fixed by:
I changed
gcc -lncursesw pager.c -o pspg -ggdb
to
gcc pager.c -o pspg -ggdb -lncursesw
If you want to use pspg as a Postgres client, then you need to run configure --with-postgresql=yes. On Fedora with my own Postgres build I had to install the openssl-devel package and I had to set export PKG_CONFIG_PATH="/usr/local/pgsql/master/lib/pkgconfig/".
On FreeBSD you should use gmake instead of make ๐
๐ฆ Note โ Installation details
When you compile code from source, run ./configure first. Sometimes ./autogen.sh first.
If you would like to display UTF-8 characters, then pspg should be linked with the ncursesw library. UTF-8 characters are displayed badly when the ncursesw library is used. You can see broken characters with an incorrect locale setting too ๐ซ
You can check wide chars support with pspg --version. A row ncurses with wide char support is expected. Re-run configure with the --with-ncursesw option. When this command fails, check if the development package for the ncursesw library is installed.
๐บ Homebrew (for Linux & MacOS)
# brew install pspg
You can compile pspg easily without brew, but you need the gnu readline library. MacOS uses by default readline emulated over libedit, but pspg requires the full gnu readline library.
LDFLAGS="-L/usr/local/opt/readline/lib" CPPFLAGS="-I/usr/local/opt/readline/include" ./configure
LDFLAGS="-L/usr/local/opt/readline/lib" CPPFLAGS="-I/usr/local/opt/readline/include" make
๐ Debian
# apt-cache search pspg
# apt-get install pspg
๐ฉ Fedora (28 and later)
# dnf install pspg
๐ด RPM (CentOS/openSUSE/โฆ)
pspg is available from the community repository https://yum.postgresql.org/packages.php
๐๏ธ Alpine Linux
# apk add pspg
๐ฟ Gentoo
# emerge -av dev-db/pspg
๐น Arch Linux
The Arch User Repository contains two versions:
pspg(https://aur.archlinux.org/packages/pspg/) is a fixed release.pspg-git(https://aur.archlinux.org/packages/pspg-git/) tracks the master branch.
Use the AUR helper of your choice, or git and makepkg, to install pspg ๐
๐ FreeBSD
# pkg install pspg
๐ก OpenBSD
# pkg_add pspg
More about it here: https://fluca1978.github.io/2021/10/28/pspgOpenBSD.html
๐ Using MacPorts (MacOS only)
# port install pspg
๐ช MS Windows
pspg can simply be used on MS Windows by using wsl2 โจ I tested it, and it's working without problems.
- In a terminal, execute
wsl --install -d Ubuntu-22.04 - In a terminal, open an Ubuntu session:
sudo apt-get update
sudo apt-get install pspg
sudo apt-get install postgresql postgresql-contrib
# set password for user postgres
sudo passwd postgres
su - postgres
psql postgres
>> create role pavel login;
\q
exit
touch ~/.psqlrc
mcedit .psqlrc
\pset linestyle unicode
\pset border 2
\setenv PSQL_PAGER 'pspg -b -X'
# press F2 and F10
psql postgres
there isn't any difference from installation and work on Ubuntu (Debian) ๐ซถ
pspg is not ported to MS Windows yet. There's the dependency on ncurses and on a correctly (fully) implemented newterm function (pdcurses does this only on Unix platforms). It can work with WSL2 maybe (I didn't test it). An alternative can be using the less pager, which is ported to some MS Win environments. less depends on termcap, and it's a little bit more portable than pspg (termcap is the low layer of ncurses). less supports fixed rows and, with the --chop-long-lines option or just -S, can be used as a pager for pspg.
export PSQL_PAGER="less --chop-long-lines --header 1"
โ๏ธ Solaris
There are a few issues requiring manual code changes for successful compilation โ we successfully tested pspg, but although pspg was linked with ncursesw libraries, the utf8 encoding support didn't work fully correctly โ probably due to some issues in the libc library ๐ญ There are problems with chars encoded to 3 bytes โ unicode borders, etc. Two-byte unicode chars should be displayed well.
You can use pspg with usual accented chars, but unicode borders should not be used. Replacement of ascii borders by special border chars (by ncurses technology) works well โ look at the Options|Force unicode borders option.
- Solaris
makedoesn't support conditional statements โ they should be removed. So, remove unsupported functionality from theMakefile(ifdef,endif), replace-includebyincludefirst. - After running configure, remove the link on the termcap library from
config.make. It is garbage produced by the readline automake script. The combination with ncurses libraries makes some linking issues.
๐ง builtin libraries
export CURSES_CFLAGS="-I/usr/include/ncurses/"
export PANEL_LIBS="-lpanelw"
./configure
๐ OpenCSW development
export CFLAGS="-m64 -I/opt/csw/include"
export LDFLAGS="-L/opt/csw/lib/64 -R/opt/csw/lib/64"
export PKG_CONFIG_PATH="/opt/csw/lib/64/pkgconfig"
./configure
๐ POSSIBLE TODO (aka the "somebody please do this" list) ๐
Okay bestie, so these are the glow-up plans for the project โ not done yet, just vibing on the wishlist ๐ญโจ
- Store data in some column format (right now the data are stored like an array of rows). With this change it could be possible to operate over columns โ hide columns, change width, cyclic iteration over columns, change order of columns, mark columns, and export only selected columns (selected rows). That's a whole new level of main character energy for the data model, no cap ๐
- Replace printing document directly to ncurses window with some smarter structure. Internally there are a lot of checks and fixes to support complex dynamic layout. The possible views should remember first row, last row, current row. Right now, these data are in global variables or in
DataDescandScrDescstructures โ lowkey a whole situation ๐ซ
๐ ST_MENU ๐
This project uses the st_menu library โ it's the implementation of CUA menubar and pulldown menu for ncurses, and it's iconic fr fr:
https://github.com/okbob/ncurses-st-menu
๐ NOTE (the part where she's being adorable) ๐
If you like it, send a postcard from your home country to my address, please ๐ซถ๐ฎ โ and yes she really means it, this is the sweetest thing ever:
Pavel Stehule
Skalice 12
256 01 Benesov u Prahy
Czech Republic
I invite any questions, comments, bug reports, patches on mail address pavel.stehule@gmail.com โ literally bring it all, the questions, the comments, the bugs, the patches, all of it ๐
And that's the whole page, bestie โ you made it to the very end, slay ๐
โจ This lil masterpiece is PSPG(1) from May 2025, and honestly? Iconic. Go forth and scroll with taste ๐ฆ๐ธ
๐ฆ where this page comes from
- alpine 3.23: pspg-doc 5.8.16-r0 ยท BSD-2-Clause
- alpine 3.24: pspg-doc 5.8.16-r0 ยท BSD-2-Clause
- nixos 26.05: pspg 5.8.16
- nixpkgs unstable: pspg 5.9.0
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms