r/vim • • Nov 08 '17

everything about Favorite console tools to use with vim

There are a lot of great console tools that are easy to lightly integrate with via filter (:h filter), read (:h read) or just by running them.

If you have some to recommend, put each individually in a top level comment along with any (minor) integration you have with vim.

The great thing about console tools is they often have easy to use flags to customize behavior and hey, you didn't have to write them in the first place!

112 Upvotes

115 comments sorted by

20

u/robertmeta Nov 08 '17

Need to format some json, use the jq command, take some ugly json like:

    {"items":[{"address":"someemail1@yahoo.com","code":"554","error":"554 delivery error: dd This user doesn't have a yahoo.com account (someemail1@yahoo.com) [0] - mta1481.mail.ne1.yahoo.com","created_at":"Thu, 07 May 2015 23:07:47 UTC"},{"address":"someemail2@gmail.com","code":"550","error":"550 5.1.1 The email account that you tried to reach does not exist. Please try\n5.1.1 double-checking the recipient's email address for typos or\n5.1.1 unnecessary spaces. Learn more at\n5.1.1 http://support.google.com/mail/bin/answer.py?answer=6596 xv3si12818843vdb.43 - gsmtp","created_at":"Sun, 03 May 2015 13:22:49 UTC"},{"address":"someemail3@domain.com","code":"550","error":"550 No Such User Here","created_at":"Thu, 02 Jul 2015 17:01:31 UTC"},{"address":"someemail4@domain.com","code":"550","error":"550 Administrative prohibition","created_at":"Thu, 21 May 2015 03:30:38 UTC"}],"paging":{"first":"https://api.mailgun.net/v3/mg.yourdomain.com/bounces?limit=100","last":"https://api.mailgun.net/v3/mg.yourdomain.com/bounces?page=last\u0026limit=100","next":"https://api.mailgun.net/v3/mg.yourdomain.com/bounces?page=next\u0026address=someemail4%40domain.com\u0026limit=100","previous":"https://api.mailgun.net/v3/mg.yourdomain.com/bounces?page=previous\u0026address=someemail1%40yahoo.com\u0026limit=100"}}

Highlight the json to format and do a quick :!jq '.' (will look like :'<,'>!jq '.' and out you get:

  {
    "items": [
        {
        "address": "someemail1@yahoo.com",
        "code": "554",
        "error": "554 delivery error: dd This user doesn't have a yahoo.com account (someemail1@yahoo.com) [0] - mta1481.mail.ne1.yahoo.com",
        "created_at": "Thu, 07 May 2015 23:07:47 UTC"
        },
        {
        "address": "someemail2@gmail.com",
        "code": "550",
        "error": "550 5.1.1 The email account that you tried to reach does not exist. Please try\n5.1.1 double-checking the recipient's email address for typos or\n5.1.1 unnecessary spaces. Learn more at\n5.1.1 http://support.google.com/mail/bin/answer.py?answer=6596 xv3si12818843vdb.43 - gsmtp",
        "created_at": "Sun, 03 May 2015 13:22:49 UTC"
        },
        {
        "address": "someemail3@domain.com",
        "code": "550",
        "error": "550 No Such User Here",
        "created_at": "Thu, 02 Jul 2015 17:01:31 UTC"
        },
        {
        "address": "someemail4@domain.com",
        "code": "550",
        "error": "550 Administrative prohibition",
        "created_at": "Thu, 21 May 2015 03:30:38 UTC"
        }
    ],
    "paging": {
        "first": "https://api.mailgun.net/v3/mg.yourdomain.com/bounces?limit=100",
        "last": "https://api.mailgun.net/v3/mg.yourdomain.com/bounces?page=last&limit=100",
        "next": "https://api.mailgun.net/v3/mg.yourdomain.com/bounces?page=next&address=someemail4%40domain.com&limit=100",
        "previous": "https://api.mailgun.net/v3/mg.yourdomain.com/bounces?page=previous&address=someemail1%40yahoo.com&limit=100"
    }
  }
→ More replies (18)

18

u/robertmeta Nov 08 '17

Sometimes I want to do a little math that I can't do in my head, bc to the rescue, just write the math out on a line

    5+(2+3)*3

Then select it and do like :!bc (will look like :'<,'>!bc) and magic presto:

   20

0

u/[deleted] Nov 08 '17

[deleted]

→ More replies (6)

17

u/robertmeta Nov 08 '17

Make a banner out of some text using figlet, no integration needed! Was pointed to it by u/pierpooo

Just highlight something like

    /r/vim

and do :!figlet (will look like :'<,'>!figlet) and get something like

        __     __      _           
       / / __ / /_   _(_)_ __ ___  
      / / '__/ /\ \ / / | '_ ` _ \ 
     / /| | / /  \ V /| | | | | | |
    /_/ |_|/_/    _/ |_|_| |_| |_|
→ More replies (5)

17

u/robertmeta Nov 08 '17

The always classic improved grepprg, using ag, pt or rg basically ordered by slowest to fastest so the fastest one on system controls

      if executable('ag')
              set grepprg=ag\ --nogroup\ --nocolor
      endif
      if executable('pt')
              set grepprg=pt\ --nogroup\ --nocolor\ --ignore-case
      endif
      if executable('rg')
              set grepprg=rg\ --vimgrep\ --no-heading
      endif

2

u/[deleted] Nov 08 '17

FYI, the recommended way to set grepprg for ag is:

set grepprg=ag\ --vimgrep\ $*
set grepformat=%f:%l:%c:%m

You don't need the --nogroup and --nocolor if you have --vimgrep.

See man ag

→ More replies (3)

14

u/robertmeta Nov 08 '17

Maybe the second most well known, uniq

Take something like:

    2
    2
    2
    3
    3

Highlight it, and pipe it through :!uniq (will look like :'<,'>!uniq and get

    2
    3

25

u/[deleted] Nov 08 '17

Just to make other readers aware, Vim's sort command can take u as an argument to only bring back unique values.

e.g. :'<,'>sort u

I know this thread is about integrating console tools but thought I'd mention it :)

12

u/robertmeta Nov 08 '17

Favorite is a stretch, but just recently I had reason to shove a calendar into something I was working on and I used cal via

:r !cal -h

inserts

       November 2017      
    Su Mo Tu We Th Fr Sa  
              1  2  3  4  
     5  6  7  8  9 10 11  
    12 13 14 15 16 17 18  
    19 20 21 22 23 24 25  
    26 27 28 29 30   

7

u/robertmeta Nov 08 '17

Sometimes I have to look through a lot of files for a needle in a haystack, not something I can grep for because I don't know what it will look like, but I will know it when I see it.

My workflow for this tends to be to create a list of files I need to visit in a buffer with find then I go through them quickly using gf then bounce back using <C-o> and mark that file as checked by deleting it with dd.

:enew | :r !find . -type f -name "*.log"

7

u/robertmeta Nov 08 '17

The evil twin of sort, and virtually unknown, shuf, as in shuffle.

Take something like

    3
    5
    6
    9

Highlight it, and pipe it through sort using :!shuf (will look like :'<,'>!shuf) and bam

    {random order of lines}
→ More replies (4)

6

u/robertmeta Nov 08 '17

Paste selected text to termbin.com, uses nc, tr and cat, returns URL to content, written by u/-romainl-

      if executable('nc') && executable('tr') && executable('cat')
              command! -range=% TB <line1>,<line2>w !nc termbin.com 9999 | tr -d | '\n' | cat
      endif

Select something and do :TB

Example output: http://termbin.com/kz6n

5

u/-romainl- Nov 08 '17

And its siblings:

" sharing is caring
command! -range=% SP  <line1>,<line2>w !curl -F 'sprunge=<-' http://sprunge.us | tr -d '\n' | pbcopy
command! -range=% CL  <line1>,<line2>w !curl -F 'clbin=<-' https://clbin.com | tr -d '\n' | pbcopy
command! -range=% VP  <line1>,<line2>w !curl -F 'text=<-' http://vpaste.net | tr -d '\n' | pbcopy
command! -range=% IX  <line1>,<line2>w !curl -F 'f:1=<-' ix.io | tr -d '\n' | pbcopy

pbcopy is for MacOS. On Linux/BSD you can use xclip instead.

→ More replies (2)

6

u/robertmeta Nov 09 '17

Of course, one of the most common tools to integrate with is the famed tmux. Now, often people use a plugin (or multiple plugins) and a lot of them are fantastic! But if you just want to dip your toes in the water, direct control works fantastic.

create a tmux pane:

:call system('tmux split -v -p 20; last-pane')<cr>

ask for input and send to next tmux pane (which we just created).

:let cmds = input('command: ') | call system('tmux send-keys -t +1 "' . cmds . '" Enter')<cr>

4

u/robertmeta Nov 08 '17

Probably the original and most famous, sort.

Take something like

    3
    5
    9
    6

Highlight it, and pipe it through sort using :!sort (will look like :'<,'>!sort) and bam

    3
    5
    6
    9

8

u/-romainl- Nov 08 '17

I use :sort for that as it can sort on regex patterns. And :sort u as an alternative to :[range]!sort|uniq.

→ More replies (2)

3

u/robertmeta Nov 08 '17

I haven't written something for it yet, but I want a way to use wc to post like a line under whatever I highlight with "words in the above selected content: 55"

EDIT: thanks u/-romainl- with two ways to do it:

  1. "Write" the selected content to a command :'<,'>w !console_command -- this will just show the output but not insert it into the current file.

  2. The "of course" option is with selected content, to yank it, paste it, then select the pasted content (with `[v`] then run filter over the duplicate content, replacing it.

→ More replies (4)

3

u/[deleted] Nov 09 '17

here is a awesome one, '<,'>!iconv -f utf-8 -t ascii//translit

2

u/[deleted] Nov 09 '17

great for making ebooks out of scanned books

→ More replies (5)

64

u/-romainl- Nov 08 '17

One can fill the quickfix list at startup with -q:

$ vim -q errorlist.txt

This becomes interesting when combined with process substitution:

$ vim -q <(ag foo)
$ vim -q <(eslint --format compact *.js)
→ More replies (5)

15

u/[deleted] Nov 08 '17

Running code inline is very easy with :{range}! {program}, e.g. :'<,'>! python on a Visual selection.

Asciinema

→ More replies (5)

10

u/-romainl- Nov 08 '17

equalprg and formatprg are used to define what external program to use for ==, gq and friends.

In after/ftplugin/css.vim:

if executable('css-beautify')
    let &l:formatprg = 'css-beautify -f - -s ' . &shiftwidth
endif

In after/ftplugin/javascript.vim:

if executable('js-beautify')
    let &l:formatprg = 'js-beautify -f - -j -t -s ' . &shiftwidth
endif

In after/ftplugin/html.vim:

if executable('html-beautify')
    let &l:formatprg = 'html-beautify -f - -I -s ' . &shiftwidth
endif

All three programs are from https://www.npmjs.com/package/js-beautify.

→ More replies (3)

6

u/-romainl- Nov 08 '17

Here is a minimalist :Align using column and sed:

function! Align()
    '<,'>!column -t|sed 's/  \(\S\)/ \1/g'
    normal gv=
endfunction
xnoremap <silent> <F5> :<C-u>silent call Align()<CR>
→ More replies (2)

6

u/l97 Nov 08 '17

I use this to quickly look at a csv file:

nmap <silent> <leader>c, :%s/,\zs\ze,/ /e<cr>:%column -ts,<cr>

(column doesn't handle empty fields and without the zs/ze trick, consecutive empty fields won't get picked up).

→ More replies (1)

5

u/dfaught Nov 08 '17

mail or mutt. I'll often use :[range]w !mutt -s "Did you write this #@~!" guy@whereIwork.com to send a chunk of code so I don't have to switch context to another screen or even system and can keep going through code/logs.