In vim, how do I start vim at the end of the file and what commands are available with -c - vim

By reading this question I learned that you can give -c to vim such that it will call a command. The question is then answered by calling vim -c startinsert. Good, but what if I want to give other commands? I only know the shortcuts like i for :startinsert.
For example I'd like to write vim -c gotoend but it doesn't exists.
After some reading, all : commands, which are ex commands are written here and in man vim, but where do I find a lis or method to know what can be done?

The commands for options -c are called ex-command named after ex(tendended line editor). The list of commands are in vimdoc and vimhelp.
The command to jump to the end of file is just :$ so you can do this in command line:
vim -c $ <file>
Please note you probably better escape or quote $ as it's a shell metacharacter:
vim -c \$ <file>
or
vim -c '$' <file>

:help :normal. Also note that instead of -c command you can use +command.
With that, I'd typically say vim +"norm G" foo.txt to start at the bottom. You could even alias it: alias vimbottom='vim +"norm G"'; then you can use vimbottom foo.txt to start at the bottom, if you prefer.
where do I find a lis or method to know what can be done
There is no better resource for Vim than its :help. And I don't know any place that has all the ex-commands in one place, since it would be a huge list. (EDIT: :help :index actually has that. Thanks, Christian Brabandt!)

Related

Running arbitrary vim commands from bash command line to script vim

I want to script vim to edit files from the command line. For example I want to do something along the lines of:
vim -<SOME_OPTION> 'Iworld<Esc>bIhello <Esc>:wq helloworld.txt<CR>'
or:
echo 'Iworld<Esc>bIhello <Esc>:wq helloworld.txt<CR>' | vim
and have it save the file helloworld.txt with a body of hello world
Is this possible? I've tried a few different approaches but none seem to do it. I realize I can do things like vim +PluginInstall to run Ex commands from the command line, but I'd love to be able to string together arbitrary motions
This can be achieved with the + flag and the :normal command:
$ vim +"norm Iworld" +"norm Ihello " +"wq helloworld.txt"
I think what you are looking for is vim's -w/W and -s {scriptin} option. Well in your case you should make a scriptfile, and with -s file to let vim execute all your "key presses"
I think vimgolf has used these options too.

vim: deleting non-matching lines in command line

I'm using vim to parse a file in the command line (I'm running gentoo linux):
One of the commands is not working as [I think] it should:
vim -c "v/pattern/d | wq" file
For some reason, this is not deleting the lines without the specified pattern when adding | wq. If I open the file with vim and run the same command, it works. If I run it in the command line without | wq it works.
Why is this not working?
The reason is that Vim sees this as :v/pattern/(d | wq), see :help :bar for an explanation. To avoid this, either wrap the :v in :execute:
vim -c "exe 'v/pattern/d' | wq" file
or, simpler, submit this as two separate commands:
vim -c "v/pattern/d" -c "wq" file
PS: Of course, #Bogdan has a point; you don't need Vim for that simple a task.
I suggest you use sed for that:
sed -i '/pattern/d' ./file

What is a way to read man pages in Vim without using temporary files

I want to be able to read man pages in Vim.
For some reason, it seems that Vim isn't able to read the output of programs through piping. E.g (man ls) | vi doesn't seem to work, bonus points for somebody who can explain why.
To get around this, I've been using the following little script:
tempo = `mktemp`
man $1 > $tempo ; vi $tempo
This script uses temporary files which I guess work fine, but I was wondering if there was a good way to read man pages in Vim without resorting to creating temporary files
Vim includes a man page viewer, :Man, in its runtime files.
Put this line in your vimrc:
runtime! ftplugin/man.vim
Now you can read syntax-highlighted man pages inside Vim by running :Man. For example:
:Man 3 printf
Even better, you can just place your cursor on a word in the buffer and press <Leader>K (\K) to see the man page for that word.
See :h find-manpage for complete usage and installation instructions.
For some reason, it seems that vim isn't able to read the output of programs through piping […]
According to the man-page, you need to specify a file of - to get it to read from standard input; so:
man ls | vi -
If that doesn't work, you might try using process substitution:
vi <(man $1)
which creates a sort of pseudo-file and passes it to vi.
On my system (Mac OS X), I found that the above left control characters in the output. Instead I used:
export MANPAGER="col -b | vim -MR - "
then just e.g.
man vim
The vim options turn off modifying the buffer and make it read-only. This stops vim complaining if you try to exit with ":q" (you can use :q! of course, but you might as well set the options).
This is also handy for general use - I have the following. The -c command names the buffer, just for completeness.
alias vimpager="vim -MR -c 'file [stdin]' -"
Here is what I did: I've made a function in my .bashrc:
vman() { vim <(man $1); }
When I call vman this automatically calls Vim showing the man page. It works great.
Your example code is wrong.
tempo=`mktemp`
man $1 > $tempo; vi $tempo
But you really only need
man $1 | vi -
By default vim reads vimscripts (=vim commands), not input files, from stdin. That is why you cannot directly pipe man output to vim; as others have mentioned you have to use vim - to make vim read from stdin.
However piping vimscripts can be useful too:
vim test.txt <<EOF
:%s/[aiueo]/X/g
:wq! output.txt
EOF
The above will use vim to open test.txt, replace all vowels with X, write the results to output.txt, and quit (ignoring changes to the original file). It uses a here document but you can of course put the vim commands in a file and use vim test.txt < myscript or cat myscript | vim test.txt to achieve the same result.
I suspect the reason they did it this way was that you can open multiple input files but only execute one script. If input was read from stdin by default, you could only read one buffer that way.
I combined others answers, I am using
vman() {
export MANPAGER="col -b" # for FreeBSD/MacOS
# Make it read-only
eval 'man $# | vim -MR +"set filetype=man" -'
unset MANPAGER
}
Usage:
vman ls
You also can press shift-k on your c function to print the man page
I have a better solution, the one that I used, it is like this:
/bin/sh -c "unset PAGER;col -b -x | vim -R -c 'set ft=man nomod nolist' -c 'map q :q<CR>' -c 'map <SPACE> <C-D>' -c 'map b <C-U>' -c 'nmap K :Man <C-R>=expand(\"<cword>\")<CR><CR>' -"
Hope you'll enjoy it.
You can always use info command for info pages and do info {cmd} | vim.
Source.
A lot of good answers, with respect to plugins it's worth to add that vim-man* provides a set of convenience functions to open and read man pages:
Viewing man pages, as per docs.
:Man printf - open printf(1) man page in a split
:Vman 3 putc - open putc(3) man page in a vertical split
:Man pri<Tab> -
command completion for man page names
* Available on GitHub: https://github.com/vim-utils/vim-man.

Search and replace in Vim across all the project files

I'm looking for the best way to do search-and-replace (with confirmation) across all project files in Vim. By "project files" I mean files in the current directory, some of which do not have to be open.
One way to do this could be to simply open all of the files in the current directory:
:args ./**
and then do the search and replace on all open files:
:argdo %s/Search/Replace/gce
However, when I do this, Vim's memory usage jumps from a couple dozen of MB to over 2 GB, which doesn't work for me.
I also have the EasyGrep plugin installed, but it almost never works—either it doesn't find all the occurrences, or it just hangs until I press CtrlC. So far my preferred way to accomplish this task it to ack-grep for the search term, using it's quickfix window open any file that contains the term and was not opened before, and finally :bufdo %s/Search/Replace/gce.
I'm looking either for a good, working plugin that can be used for this, or alternatively a command/sequence of commands that would be easier than the one I'm using now.
The other big option here is simply not to use vim:
sed -i 's/pattern/replacement/' <files>
or if you have some way of generating a list of files, perhaps something like this:
find . -name *.cpp | xargs sed -i 's/pattern/replacement/'
grep -rl 'pattern1' | xargs sed -i 's/pattern2/replacement/'
and so on!
EDIT: Use cfdo command instead of cdo to significantly reduce the amount of commands that will be run to accomplish this (because cdo runs commands on each element while cfdo runs commands on each file)
Thanks to the recently added cdo command, you can now do this in two simple commands using whatever grep tool you have installed. No extra plugins required!:
1. :grep <search term>
2. :cdo %s/<search term>/<replace term>/gc
3. (If you want to save the changes in all files) :cdo update
(cdo executes the given command to each term in the quickfix list, which your grep command populates.)
(Remove the c at the end of the 2nd command if you want to replace each search term without confirming each time)
I've decided to use ack and Perl to solve this problem in order to take advantage of the more powerful full Perl regular expressions rather than the GNU subset.
ack -l 'pattern' | xargs perl -pi -E 's/pattern/replacement/g'
Explanation
ack
ack is an awesome command line tool that is a mix of grep, find, and full Perl regular expressions (not just the GNU subset). Its written in pure Perl, its fast, it has syntax highlighting, works on Windows and its friendlier to programmers than the traditional command line tools. Install it on Ubuntu with sudo apt-get install ack-grep.
xargs
Xargs is an old unix command line tool. It reads items from standard input and executes the command specified followed by the items read for standard input. So basically the list of files generated by ack are being appended to the end of the perl -pi -E 's/pattern/replacemnt/g' command.
perl -pi
Perl is a programming language. The -p option causes Perl to create a loop around your program which iterates over filename arguments. The -i option causes Perl to edit the file in place. You can modify this to create backups. The -E option causes Perl to execute the one line of code specified as the program. In our case the program is just a Perl regex substitution. For more information on Perl command line options perldoc perlrun. For more information on Perl see http://www.perl.org/.
Greplace works well for me.
There's also a pathogen ready version on github.
maybe do this:
:noautocmd vim /Search/ **/*
:set hidden
:cfirst
qa
:%s//Replace/gce
:cnf
q
1000#a
:wa
Explanation:
:noautocmd vim /Search/ **/* ⇒ lookup (vim is an abbreviation for vimgrep) pattern in all files in all subdirectories of the cwd without triggering autocmds (:noautocmd), for speed's sake.
:set hidden ⇒ allow having modified buffers not displayed in a window (could be in your vimrc)
:cfirst ⇒ jump to first search result
qa ⇒ start recording a macro into register a
:%s//Replace/gce ⇒ replace all occurrences of the last search pattern (still /Search/ at that time) with Replace:
several times on a same line (g flag)
with user confirmation (c flag)
without error if no pattern found (e flag)
:cnf ⇒ jump to next file in the list created by the vim command
q ⇒ stop recording macro
1000#a ⇒ play macro stored in register a 1000 times
:wa ⇒ save all modified buffers
* EDIT * Vim 8 way:
Starting with Vim 8 there is a better way to do it, as :cfdo iterates on all files in the quickfix list:
:noautocmd vim /Search/ **/*
:set hidden
:cfdo %s//Replace/gce
:wa
Populate :args from a shell command
It's possible (on some operating systems1)) to supply the files for :args via a shell command.
For example, if you have ack2 installed,
:args `ack -l pattern`
will ask ack to return a list of files containing 'pattern' and put these on the argument list.
Or with plain ol' grep i guess it'd be:
:args `grep -lr pattern .`
You can then just use :argdo as described by the OP:
:argdo %s/pattern/replacement/gce
Populate :args from the quickfix list
Also check out nelstrom's answer to a related question describing a simple user defined command that populates the arglist from the current quickfix list. This works great with many commands and plugins whose output ends up in the quickfix list (:vimgrep, :Ack3, :Ggrep4).
The sequence to perform a project wide search could then be done with:
:vimgrep /pattern/ **/*
:Qargs
:argdo %s/findme/replacement/gc
where :Qargs is the call to the user defined command that populates the arglist from the quickfix list.
You'll also find links in the ensuing discussion to simple plugins that get this workflow down to 2 or 3 commands.
Links
:h {arglist} - vimdoc.sourceforge.net/htmldoc/editing.html#{arglist}
ack - betterthangrep.com/
ack.vim - github.com/mileszs/ack.vim
fugitive - github.com/tpope/vim-fugitive
One more option in 2016, far.vim plugin:
1. :grep <search term> (or whatever you use to populate the quickfix window)
2. :cfdo %s/<search term>/<replace term>/g | update
Step 1 populates the quickfix list with items you want. In this case, it's propagated with search terms you want to change via grep.
cfdo runs the command following on each file in the quickfix list. Type :help cfdo for details.
s/<search term>/<replace term>/g replaces each term. /g means replace every occurrence in the file.
| update saves the file after every replace.
I pieced this together based upon this answer and its comments, but felt it deserved its own answer since it's all in one place.
If you don't mind of introducing external dependency, I have brewed a plugin ctrlsf.vim (depends on ack or ag) to do the job.
It can format and display search result from ack/ag, and synchronize your changes in result buffer to actual files on disk.
Maybe following demo explains more
Make sure you’re using Neovim (or Vim 7.4.8+, but really just use Neovim)
Install FZF for the command line and as a vim plugin
Install Ag, so that it’s available automatically to FZF in vim
If using iTerm2 on OSX, set the alt/option key to Esc+
Usage
Search the text you want to change in the current directory and it’s children with
:Ag text
Keep typing to fuzzy filter items
Select items with alt-a
Deselect items with alt-d
Enter will populate the quickfix list
:cfdo %s/text/newText/g | :w
Now you have chabges made inside Vim NeoVim
source
You can do it with shell and vim's ex-mode. This has the added benefit of not needing to memorize other search-and-replace escape sequences.
Any command that can list files will work (rg -l, grep -rl, fd...). For example in bash:
for f in $(rg -l Search); do
vim -Nes "$f" <<EOF
%s/Search/Replace/g
wq
EOF
done
You can use any command, those prefixed with : in command mode, the same way you would inside vim, just drop the : at the start
I think that is because you have a huge amount of files been captured in memory. For my case, I do this by group files in different types, for example:
:args **/*.md
argdo <command>
:args **/*.haml
argdo <command>
Basically, I wanted the replace in a single command and more importantly within vim itself
Based on the answer by #Jefromi i've created a keyboard shortcut, which I had set in my .vimrc file like this
nmap <leader>r :!grep -r -l * \| xargs sed -i -e 's///g'
now from the vim, on a stroke of leader+r I get the command loaded in vim, which i edit like below,
:!grep -r -l <find> <file pattern> | xargs sed -i -e 's/<find>/<replace>/g'
Hence, I do the replace with a single command and more importantly within vim itself

escape character in vim command

I want to run command like this:
vim -c "%g/blablabla/norm /str<ESC>cwSTR" file
How I write escape character in the command?
As you type the command, use control-v then escape to enter the escape.
However, I have to question whether vim is the right tool for this job. Normally, you would be better off with something like sed. That said, I'm not quite clear what the vim command is up to, so maybe you do need it.
This is what I would do:
vim -s -c ':exec "normal %g/blablabla/norm /str\<Esc>cwSTR"' file
Notice that I am using :exec to expand the "\" to the real . The advantage? it is more script friendly. However, I am not sure what this command is doing, are you using some of your custom maps here?

Resources