Using the content of a register in a ex command - vim

Buffer 0 contains the name of a file that I want to insert in the current vim buffer.
What I try doesn't work:
:r #0
In general, how can one use the content of a register in an ex script?

There are multiple ways:
When typing the command interactively, the <C-R> command inserts a register (or Vimscript expression via the = register): :r <C-r>0 There are many useful variants, see :help c_CTRL-R. You can also use this in a mapping, though I would prefer the alternative:
Interpolating the register contents via :execute, i.e. you're building the command as a string first: :execute 'read ' . #0

Related

vimscript - edit another file from a custom command

I'd like to create, move around and append to other_file.py after calling a custom command from within this_file.py.
So for instance, I'd like to write several lines of text to a range of lines in the other file.
Is there some way I can basically enter :edit mode in other_file.py from this function? This would allow me to move around, search and append to other_file as though I were in it.
Here's a run through of where I'm at:
I am in this_file.py, and I have called:
:MyComm other_file:line_1/line_2/line_3
This activates the following vimscript:
function MyFunc(param_string)
let param_split = split(a:param_string,":")
let file_name = param_split[0] . ".py"
let lines = split(class_split[1],"/")
call system("touch " . file_name)
" Here is where I want to loop through the lines and use them in other_file.py
endfunction
:command -nargs=1 MyComm :call MyFunc(<f-args>)
alternative A
You can continue going through the external commands, as you've started with touch. So, you could use sed or awk to replace / append lines to the other file. With Vim's system() command, you can pass stdin input, too. For example, if you want to copy lines from the current buffer, grab them with getline() and pass them to system(), either as a List or a String.
alternative B
However, I would recommend avoiding external commands, and do the text editing tasks inside Vim. For that you just need to :execute 'split' other_file, and do the edits just as you would interactively, using Ex commands or :normal. Note that there are some special Ex commands (like :wincmd w replacing <C-w>w normal mode commands) that can make this more readable.

Vim: Issue normal-mode commands in user-defined command

I'm certain this will have been asked somewhere, but I can't for the life of me find it, and it's not in the Defining command-line commands section of the Vim documentation.
I want to create a user-defined command which will insert the word foo before the current word.
(Note: I want it to be a function because I don't trust myself to remember yet another shortcut key. I know how to do it with noremap...)
In my .vimrc I add:
command AddFoo bifoo<esc>w
But when I type :AddFoo I get Not an editor command: bifoow.
Is it possible to have a function which issues normal mode commands?
The :normal Ex command allows to issue arbitrary normal mode commands.
command AddFoo normal! bifoo<esc>w
If you want to interpolate expressions etc., you need to use :execute; I'll just show your example again with the use of :help key-notation:
command AddFoo execute "normal! bifoo\<esc>w"
The ! after :normal prevents the use of custom mappings, like :noremap (vs :map).
Please make sure you get the difference between a command and a function.
The right hand side of a command definition is supposed to be at least one Ex command like write or bnext:
command! Foo update | tabnext
You can call a function:
command! Bar call Bar()
or execute a normal mode macro:
command! Baz normal ciw"<C-r>""
See :help :normal.
Should be simple to get what you want, you just need to switch to normal mode to make your changes:
command AddFoo normal bifoo<esc>w

vim: vnew, but accepting a buffer instead of a filename?

Currently, if I want to create a new window then load a buffer, I use :vnew :buf foo.py. Is there one command which will do both?
Yes, there is a command for that:
:[N]sb[uffer] [N] :sb :sbuffer
Split window and edit buffer [N] from the buffer list. If [N]
is not given, the current buffer is edited. Respects the
"useopen" setting of 'switchbuf' when splitting. This will
also edit a buffer that is not in the buffer list, without
setting the 'buflisted' flag.
You may find these ones useful also:
:[N]sbn[ext] [N] :sbn :sbnext
Split window and go to [N]th next buffer in buffer list.
Wraps around the end of the buffer list. Uses 'switchbuf'
:[N]sbN[ext] [N] :sbN :sbNext :sbp :sbprevious
:[N]sbp[revious] [N]
Split window and go to [N]th previous buffer in buffer list.
Wraps around the start of the buffer list.
Uses 'switchbuf'.
The problem with both commands is that they will split horizontally. You can precede them with :vert[ical], but that breaks your one command paradigm :-)
Anyway, :vert sb foo.py is not that much of typing, and if you really use it often, you might want to consider creating a map for it. Maybe something like:
cnoremap ,sb vert sb
Just tell :vnew the path to the file:
:vnew foo.py
Edit:
As sidyll said, there is no built in command that splits the window vertically to edit a buffer, then I have created a new ex commands which does what you want:
command! -nargs=1 -complete=buffer -bang Vbuffer vnew | buf<bang> <args>
The ! after command will replace an old :Vbuffer if it exists (you can remove that since I have added it for testing), -nargs=1 means that the new command accepts 1 argument which is passed to the :buf command with <args>, -complete=buffer will suggest buffer names as you type tab for the argument name and -bang indicates that the new command accepts the ! option which is also passed to the :buf command with <bang>.
Just add that line to your ~/.vimrc and re-:source it. ;-)

How to paste yanked text into the Vim command line

I'd like to paste yanked text into Vim's command line. Is it possible?
Yes. Hit Ctrl-R then ". If you have literal control characters in what you have yanked, use Ctrl-R, Ctrl-O, ".
Here is an explanation of what you can do with registers. What you can do with registers is extraordinary, and once you know how to use them you cannot live without them.
Registers are basically storage locations for strings. Vim has many registers that work in different ways:
0 (yank register: when you use y in normal mode, without specifying a register, yanked text goes there and also to the default register),
1 to 9 (shifting delete registers, when you use commands such as c or d, what has been deleted goes to register 1, what was in register 1 goes to register 2, etc.),
" (default register, also known as unnamed register. This is where the " comes in Ctrl-R, "),
a to z for your own use (capitalized A to Z are for appending to corresponding registers).
_ (acts like /dev/null (Unix) or NUL (Windows), you can write to it but it's discarded and when you read from it, it is always empty),
- (small delete register),
/ (search pattern register, updated when you look for text with /, ?, * or # for instance; you can also write to it to dynamically change the search pattern),
: (stores last VimL typed command via Q or :, readonly),
+ and * (system clipboard registers, you can write to them to set the clipboard and read the clipboard contents from them)
See :help registers for the full reference.
You can, at any moment, use :registers to display the contents of all registers. Synonyms and shorthands for this command are :display, :reg and :di.
In Insert or Command-line mode, Ctrl-R plus a register name, inserts the contents of this register. If you want to insert them literally (no auto-indenting, no conversion of control characters like 0x08 to backspace, etc), you can use Ctrl-R, Ctrl-O, register name.
See :help i_CTRL-R and following paragraphs for more reference.
But you can also do the following (and I probably forgot many uses for registers).
In normal mode, hit ":p. The last command you used in vim is pasted into your buffer.
Let's decompose: " is a Normal mode command that lets you select what register is to be used during the next yank, delete or paste operation. So ": selects the colon register (storing last command). Then p is a command you already know, it pastes the contents of the register.
cf. :help ", :help quote_:
You're editing a VimL file (for instance your .vimrc) and would like to execute a couple of consecutive lines right now: yj:#"Enter.
Here, yj yanks current and next line (this is because j is a linewise motion but this is out of scope of this answer) into the default register (also known as the unnamed register). Then the :# Ex command plays Ex commands stored in the register given as argument, and " is how you refer to the unnamed register. Also see the top of this answer, which is related.
Do not confuse " used here (which is a register name) with the " from the previous example, which was a Normal-mode command.
cf. :help :# and :help quote_quote
Insert the last search pattern into your file in Insert mode, or into the command line, with Ctrl-R, /.
cf. :help quote_/, help i_CTRL-R
Corollary: Keep your search pattern but add an alternative: / Ctrl-R, / \|alternative.
You've selected two words in the middle of a line in visual mode, yanked them with y, they are in the unnamed register. Now you want to open a new line just below where you are, with those two words: :pu. This is shorthand for :put ". The :put command, like many Ex commands, works only linewise.
cf. :help :put
You could also have done: :call setreg('"', #", 'V') then p. The setreg function sets the register of which the name is given as first argument (as a string), initializes it with the contents of the second argument (and you can use registers as variables with the name #x where x is the register name in VimL), and turns it into the mode specified in the third argument, V for linewise, nothing for characterwise and literal ^V for blockwise.
cf. :help setreg(). The reverse functions are getreg() and getregtype().
If you have recorded a macro with qa...q, then :echo #a will tell you what you have typed, and #a will replay the macro (probably you knew that one, very useful in order to avoid repetitive tasks)
cf. :help q, help #
Corollary from the previous example: If you have 8go in the clipboard, then #+ will play the clipboard contents as a macro, and thus go to the 8th byte of your file. Actually this will work with almost every register. If your last inserted string was dd in Insert mode, then #. will (because the . register contains the last inserted string) delete a line. (Vim documentation is wrong in this regard, since it states that the registers #, %, : and . will only work with p, P, :put and Ctrl-R).
cf. :help #
Don't confuse :# (command that plays Vim commands from a register) and # (normal-mode command that plays normal-mode commands from a register).
Notable exception is #:. The command register does not contain the initial colon neither does it contain the final carriage return. However in Normal mode, #: will do what you expect, interpreting the register as an Ex command, not trying to play it in Normal mode. So if your last command was :e, the register contains e but #: will reload the file, not go to end of word.
cf. :help #:
Show what you will be doing in Normal mode before running it: #='dd' Enter. As soon as you hit the = key, Vim switches to expression evaluation: as you enter an expression and hit Enter, Vim computes it, and the result acts as a register content. Of course the register = is read-only, and one-shot. Each time you start using it, you will have to enter a new expression.
cf. :help quote_=
Corollary: If you are editing a command, and you realize that you should need to insert into your command line some line from your current buffer: don't press Esc! Use Ctrl-R =getline(58) Enter. After that you will be back to command line editing, but it has inserted the contents of the 58th line.
Define a search pattern manually: :let #/ = 'foo'
cf. :help :let
Note that doing that, you needn't to escape / in the pattern. However you need to double all single quotes of course.
Copy all lines beginning with foo, and afterwards all lines containing bar to clipboard, chain these commands: qaq (resets the a register storing an empty macro inside it), :g/^foo/y A, :g/bar/y A, :let #+ = #a.
Using a capital register name makes the register work in append mode
Better, if Q has not been remapped by mswin.vim, start Ex mode with Q, chain those “colon commands” which are actually better called “Ex commands”, and go back to Normal mode by typing visual.
cf. :help :g, :help :y, :help Q
Double-space your file: :g/^/put _. This puts the contents of the black hole register (empty when reading, but writable, behaving like /dev/null) linewise, after each line (because every line has a beginning!).
Add a line containing foo before each line: :g/^/-put ='foo'. This is a clever use of the expression register. Here, - is a synonym for .-1 (cf. :help :range). Since :put puts the text after the line, you have to explicitly tell it to act on the previous one.
Copy the entire buffer to the system clipboard: :%y+.
cf. :help :range (for the % part) and :help :y.
If you have misrecorded a macro, you can type :let #a=' Ctrl-R =replace(#a,"'","''",'g') Enter ' and edit it. This will modify the contents of the macro stored in register a, and it's shown here how you can use the expression register to do that. Another, simpler, way of modifying a macro is to paste it in a buffer ("ap), edit it, and put it again into the register, by selecting it and "ay.
If you did dddd, you might do uu in order to undo. With p you could get the last deleted line. But actually you can also recover up to 9 deletes with the registers #1 through #9.
Even better, if you do "1P, then . in Normal mode will play "2P, and so on.
cf. :help . and :help quote_number
If you want to insert the current date in Insert mode: Ctrl-R=strftime('%y%m%d')Enter.
cf. :help strftime()
Once again, what can be confusing:
:# is a command-line command that interprets the contents of a register as vimscript and sources it
# in normal mode command that interprets the contents of a register as normal-mode keystrokes (except when you use : register, that contains last played command without the initial colon: in this case it replays the command as if you also re-typed the colon and the final return key).
" in normal mode command that helps you select a register for yank, paste, delete, correct, etc.
" is also a valid register name (the default, or unnamed, register) and therefore can be passed as an arguments for commands that expect register names
For pasting something that is the system clipboard you can just use SHIFT - INS.
It works in Windows, but I am guessing it works well in Linux too.
"I'd like to paste yanked text into Vim command line."
While the top voted answer is very complete, I prefer editing the command history.
In normal mode, type: q:. This will give you a list of recent commands, editable and searchable with normal vim commands. You'll start on a blank command line at the bottom.
For the exact thing that the article asks, pasting a yanked line (or yanked anything) into a command line, yank your text and then: q:p (get into command history edit mode, and then (p)ut your yanked text into a new command line. Edit at will, enter to execute.
To get out of command history mode, it's the opposite. In normal mode in command history, type: :q + enter
For pasting something from the system clipboard into the Vim command line ("command mode"), use Ctrl+R followed by +. For me, at least on Ubuntu, Shift+Ins is not working.
PS: I am not sure why Ctrl+R followed by *, which is theoretically the same as Ctrl+R followed by + doesn't seem to work always. I searched and discovered the + version and it seems to work always, at least on my box.
It's worth noting also that the yank registers are the same as the macro buffers. In other words, you can simply write out your whole command in your document (including your pasted snippet), then "by to yank it to the b register, and then run it with #b.
For context, this information comes from out-of-the-box, no plugins, no .vimrc Vim 7.4 behavior in Linux Mint with the default options.
You can always select text with the mouse (or using V or v and placing the selection in the "* register), and paste it into the command line with Shift + Ctrl + v.
Typing Ctrl + r in the command line will cause a prompt for a register name. so typing :CTRL-r* will place the content register * into the command line. It will paste any register, not just "*. See :help c_CTRL-R.
Furthermore, the middle mouse button will paste into the command line.
See :help->quote-plus for a description of the how X Window deals with selection. Even in a plain, out-of-the-box Vim (again, in Vim 7.4 in Linux Mint, anyway), any selection made with the left mouse button can be pasted in the command line with the middle mouse button.
In addition, the middle mouse button will also paste text selected in Vim into many other X Window applications, even GUI ones (for example, Firefox and Thunderbird) and pasting text into the command line is also possible where the text was selected from other apps.
See :help->x11-selection for addl information.
tl;dr
Try the :CTRL-r approach first, and then use Shift + Ctrl + v or the middle mouse button if you need something else.
It is conceded that it can be confusing.
I was having a similar problem. I wanted the selected text to end up in a command, but not rely on pasting it in. Here's the command I was trying to write a mapping for:
:call VimuxRunCommand("python")
The docs for this plugin only show using string literals. The following will break if you try to select text that contains doublequotes:
vnoremap y:call VimuxRunCommand("<c-r>"")<cr>
To get around this, you just reference the contents of the macro using # :
vnoremap y:call VimuxRunCommand(#")<cr>
Passes the contents of the unnamed register in and works with my double quote and multiline edgecases.
OS X
If you are using Vim in Mac OS X, unfortunately it comes with older version, and not complied with clipboard options. Luckily, Homebrew can easily solve this problem.
Install Vim:
brew install vim --with-lua --with-override-system-vi
Install the GUI version of Vim:
brew install macvim --with-lua --with-override-system-vi
Restart the terminal for it to take effect.
Append the following line to ~/.vimrc
set clipboard=unnamed
Now you can copy the line in Vim with yy and paste it system-wide.
"[a-z]y: Copy text to the [a-z] register
Use :! to go to the edit command
Ctrl + R: Follow the register identity to paste what you copy.
It used to CentOS 7.
If you have two values yanked into two different registers (for example register a and register b) then you can simply set a variable c and do the operation on it.
For example, :set c = str2float(#a) + str2float(#b) and then you can paste the content of c anywhere.
For example whilst in INSERT mode, CTRL + R then type = to enter into the expression register and just type c after equal sign and hit ENTER. Done you should now have the total of a and b registers.
All these can be recorded in a macro and repeated over!
The str2float function is used if you are working with floats, if you don't, you will get integers instead.
I am not sure if this is idiomatic but it worked for my case where I needed to add 2 numbers in a row and repeat it for 500 more lines.
I like to use Control-v to paste from the system clipboard, so I use:
cnoremap <C-v> <C-r>+

What's the use of the exclamation mark ('!') in Vim's command line after certain commands like ":w!"?

Basically I would like to know the difference between: :w and :w! or :wq and :wq!
The ! qualifier tells Vim to force the operation. For example, if the file was read-only you would use :w! to write it anyway. If the file was modified and you wanted to quit without saving, you would use :q!. :wq! just means force write and quit in one command.
In your examples the exclamation point means to force the action (e.g. :w! will overwrite an existing file and :q! will quit without saving).
That said, there are many other uses depending on the command, e.g.:
:set <option>! toggles a boolean option, e.g. :set number!
! followed by some shell command executes that command directly from the
editor, e.g. :! ls /etc
:w !cmd pipes the contents of the current buffer to the command cmd, e.g. :w !sudo tee % (a.k.a. the write with sudo trick).
Besides the situations where the exclamation point forces things, like writes, it will turn a command into a toggle command. So if I do:
:set cursorline
the line my cursor is on will be highlighted. I can turn it off with:
:set nocursorline
Or I could do:
:set cursorline!
That command flips between the two settings, off and on.
I turn cursor line highlighting off and on frequently, and the toggle command lets me do it with a simple function key mapping. Without the toggle, I would need either two mappings: one to turn it on, and a second to turn it off. Or I would have to write a function to determine whether the cursorline setting was on or off, and then turn on the opposite setting.
This works with, as far as I know, all command line settings that have on and off settings, like hlsearch, paste, cursorcolumn, number, insearch, etc.
Note also that the exclamation point will toggle the no version of the command. For example, you could also toggle the cursor line setting with:
:set nocursorline!
It really depends on the command considered. Regarding the ones you have enumerated, it forces the command as others have already answered you.
However, there are other commands like :global, :map, :make, :silent, ..., where the bang (!) has other effects. Read their documentation:
:help help
(and we can give the bang any meaning we want in the commands we define)
example
meaning
:wq! :q!
do it anyway!
:autocmd! {group} {event} {pat} cmd
override specific autocommands (:help autocmd-remove*)
:function!
override existing
:com[mand][!] [{attr}...] {cmd} {repl}
override existing
:set number!
(override 0 with 1, or 1 → 0) toggle an option
:!ls
shell command
:com[mand][!] [{attr}...] {cmd} {repl}
Define a user command. The name of the command is
{cmd} and its replacement text is {repl}. The
command's attributes (see below) are {attr}. If the
command already exists, an error is reported, unless a
! is specified, in which case the command is
Command attributes
User-defined commands are treated by Vim just like any other Ex commands. They
can have arguments, or have a range specified. Arguments are subject to
completion as filenames, buffers, etc. Exactly how this works depends upon the
command's attributes, which are specified when the command is defined.
There are a number of attributes, split into four categories: argument
handling, completion behavior, range handling, and special cases. The
attributes are described below, by category.
......
Special cases
:command-bang :command-bar
:command-register :command-buffer
:command-keepscript
There are some special cases as well:
-bang The command can take a ! modifier (like :q or :w)
-bar The command can be followed by a "|" and another command.
A "|" inside the command argument is not allowed then.
Also checks for a " to start a comment.
shell
example
meaning
#! /bin/sh
shabang
!!
last history
!2
second last history
ptipython
example
meaning
:!ls
shell command

Resources