CSV to Markdown in Vim


Requirements


Open a CSV table (I made this one with :r!sed 's/:/,/g' /etc/passwd | head).

 1root,x,0,0,,/root,/bin/bash
 2bin,x,1,1,,/,/usr/bin/nologin
 3daemon,x,2,2,,/,/usr/bin/nologin
 4mail,x,8,12,,/var/spool/mail,/usr/bin/nologin
 5ftp,x,14,11,,/srv/ftp,/usr/bin/nologin
 6http,x,33,33,,/srv/http,/usr/bin/nologin
 7nobody,x,65534,65534,Nobody,/,/usr/bin/nologin
 8dbus,x,81,81,System Message Bus,/,/usr/bin/nologin
 9systemd-coredump,x,981,981,systemd Core Dumper,/,/usr/bin/nologin
10systemd-network,x,980,980,systemd Network Management,/,/usr/bin/nologin

Highlight the table.

  • Go to the top, with 'root'.
  • Type V9j.
  • :!column -ts, -o '|'
  • Return!
 1root            |x|0    |0    |                          |/root          |/bin/bash
 2bin             |x|1    |1    |                          |/              |/usr/bin/nologin
 3daemon          |x|2    |2    |                          |/              |/usr/bin/nologin
 4mail            |x|8    |12   |                          |/var/spool/mail|/usr/bin/nologin
 5ftp             |x|14   |11   |                          |/srv/ftp       |/usr/bin/nologin
 6http            |x|33   |33   |                          |/srv/http      |/usr/bin/nologin
 7nobody          |x|65534|65534|Nobody                    |/              |/usr/bin/nologin
 8dbus            |x|81   |81   |System Message Bus        |/              |/usr/bin/nologin
 9systemd-coredump|x|981  |981  |systemd Core Dumper       |/              |/usr/bin/nologin
10systemd-network |x|980  |980  |systemd Network Management|/              |/usr/bin/nologin

The command displays as :'<,'>!column -ts, -o '|'.

This looks better, but the spacing is bad because the output separate is -o '|'. You can put spaces around that pipe by making the separator a pipe (-s'|') and making the output separator a pipe with spaces (-o' | ').

1:'<,'>!column -ts'|' -o ' | '
 1root             | x | 0     | 0     |                            | /root           | /bin/bash
 2bin              | x | 1     | 1     |                            | /               | /usr/bin/nologin
 3daemon           | x | 2     | 2     |                            | /               | /usr/bin/nologin
 4mail             | x | 8     | 12    |                            | /var/spool/mail | /usr/bin/nologin
 5ftp              | x | 14    | 11    |                            | /srv/ftp        | /usr/bin/nologin
 6http             | x | 33    | 33    |                            | /srv/http       | /usr/bin/nologin
 7nobody           | x | 65534 | 65534 | Nobody                     | /               | /usr/bin/nologin
 8dbus             | x | 81    | 81    | System Message Bus         | /               | /usr/bin/nologin
 9systemd-coredump | x | 981   | 981   | systemd Core Dumper        | /               | /usr/bin/nologin
10systemd-network  | x | 980   | 980   | systemd Network Management | /               | /usr/bin/nologin

Make a header by copying the top line and replacing text (yypkR).

That's nicer, but the formatting's wrong again.

1User             | Passwords | UID   | GID   | Description                | Home            | Shell    
2root             | x | 0     | 0     |                            | /root           | /bin/bash
3[...]

Time to fix it with :'<,'>!column -ts'|' -o'|'.

 1User              |  Passwords  |  UID    |  GID    |  Description                 |  Home             |  Shell    
 2----------------- | ----------- | ------- | ------- | ---------------------------- | ----------------- | ----------
 3root              |  x          |  0      |  0      |                              |  /root            |  /bin/bash
 4bin               |  x          |  1      |  1      |                              |  /                |  /usr/bin/nologin
 5daemon            |  x          |  2      |  2      |                              |  /                |  /usr/bin/nologin
 6mail              |  x          |  8      |  12     |                              |  /var/spool/mail  |  /usr/bin/nologin
 7ftp               |  x          |  14     |  11     |                              |  /srv/ftp         |  /usr/bin/nologin
 8http              |  x          |  33     |  33     |                              |  /srv/http        |  /usr/bin/nologin
 9nobody            |  x          |  65534  |  65534  |  Nobody                      |  /                |  /usr/bin/nologin
10dbus              |  x          |  81     |  81     |  System Message Bus          |  /                |  /usr/bin/nologin
11systemd-coredump  |  x          |  981    |  981    |  systemd Core Dumper         |  /                |  /usr/bin/nologin
12systemd-network   |  x          |  980    |  980    |  systemd Network Management  |  /                |  /usr/bin/nologin

Now we just need the spacer line. Copy the top line (yyp) and replace (:s/not-pipe/-/g). You can say 'not the pipe symbol' with [^|] or 'not-pipe-or-colon' with [^:|].

1:s/[^:|]/-/g

Keyboard Shortcut

Put this in your ~/.vimrc to map 'Control + s' to reformat CSV while in visual mode.

1vmap <C-s> :!column -ts, -o " \| "<Enter>yyp:s/[^\|:]/-/g<Enter>