Hacker News new | ask | show | jobs
by AdieuToLogic 1095 days ago
> Moving text is great in vim but being embedded in the terminal means all the powers of the shell are one ! away as well that makes it faster to do things…

Quite true.

Also, partial buffer manipulation can be done with external programs via range constraints. For example, to reverse sort only the first 5 lines of in buffer, one can execute this ex[0] command:

  :1,5 !sort -r
0 - https://man.freebsd.org/cgi/man.cgi?query=ex&apropos=0&sekti...
2 comments

I like to use vi as a kind of IDE for shell commands, because you can, for example,

!}somecommand

to pipe a paragraph through that command, or

1G!Gsomecommand

to pipe the whole editing buffer through that command, which is also equivalent to

:1,$!somecommand

which I find less obvious as a way to do that, even though it makes sense historically in terms of ed and ex.

You can also, in vim, use u and ^R to undo your pipe transformation and redo it, so you're basically then doing a series of shell pipe transformations with interactive history.

If you need to generate text with a shell command instead of pipe existing text through it, you can use

:r!somecommand

Commands that I like to use in this context include tac, rev, tr, cut, grep, and sed (although using sed this way is a little silly since the substitutions I'm doing are normally also available natively inside of vi itself).

A simple example that I like a lot is

1G!Ggrep .

which removes all empty lines from the current file. ("Line 1 go to line, pipe from here to result of movement go to end of file, command 'grep .' [print lines that match 'any character']")

The classic ed/ex way to do this is

:1,$g/^$/d

which is just as many characters, but which requires lots of explicit thought for me, while the "1G!G grep ." version seems to no longer require explicit thought at all. ("For lines 1 to last line, repeatedly match ^$ [line beginning immediately followed by line end], delete matching lines.")

Does :% not work in vi as an abbreviation of :1,$ ? The classic :%s/foo/bar/ generalises to :%!somecommand .
It does, thanks for the reminder!
> For example, to reverse sort only the first 5 lines of in buffer, one can execute this ex[0] command:

> :1,5 !sort -r

Interestingly enough, you don't even need an external program for that. You can do the same thing with

    :1,5 g/^/ m 0
The g command allows for effectively looping over matching lines as opposed to operating on them all at once. The /^/ matches every line and since I'm using 1,5 for the address, it still only matches the first five lines. The m command moves a line (in this case, 0 which is the beginning of the buffer).

Since it executes it one line at a time, it moves the first line to the beginning of the buffer, then the second line (which places it above the first line), then the third line (placing it above the second line) and so on.

Your command doesn't sort, only inverses the initial order. It's equivalent to

  :1,5 !tac