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

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

Related

Unable to successfully use custom mapped vim commands from vimrc (mac)

I am trying to add a command to my .vimrc and use it.
I have recorded a macro (in the register h) that prints the following (ending with a newline):
one
two
three
I can see this in the register h by typing :reg. It looks like:
"h ione^Mtwo^Mthree^M^[
I've pasted this as well as an alternate version in my .vimrc under test and test2 respectively:
map <Leader>test ione^Mtwo^Mthree^M^[
map <Leader>test2 ione<C-R>two<C-R>three<C-R><ESC>
My understanding is that test uses characters that can't be displayed such as ^M and ^[, so I've created test2 with what I've read is the .vimrc equivalent.
After restarting vim (which I assume means starting another vim session after this .vimrc has been written to), I test these out.
In normal mode (after hitting ESC multiple times), I try both of the following:
:test
:test2
In both cases, I'm given the error for each respectively:
E492: Not an editor command: test
E492: Not an editor command: test2
After no avail, I check to see if what I've mapped has been mapped.
In normal mode, I type :map and do indeed see what I've added, but they appear with a backslash:
\test2 ione<C-R>two<C-R>three<C-R><Esc>
\test ione^Mtwo^Mthree^M^[
Finally, in normal mode, I try again, this time with a backslash. I try both of the following:
:\test
:\test2
This time, I receive the following error for both commands:
E10: \ should be followed by /, ? or &
I am on a mac and have tried using both Terminal (which comes with OSX) as well as iTerm2.
Could someone please lend me some guidance?
your mappings are executed if you press your leader key followed by the keys test or test2. You did not create commands (:).
If you want them as command, then you don't need a mapping, but something along the lines of this in your .vimrc:
function! Test()
execute "normal ione"
execute "normal otwo"
execute "normal othree"
execute "normal o"
endfunc
command -nargs=0 Test call Test()
Which you can then use as :Test.
However, if you want to make a mapping and not a command, you might want:
a shorter mapping to type (this is very subjective),
to use nnoremap instead of map (To be usable in normal mode only, and to not recursively execute mappings),
your test2 is what you need (that I change here into <leader>t)
<C-R> is Control R, you want <CR> for the return key.
Here's an example:
nnoremap <Leader>t ione<CR>two<CR>three<CR><ESC>

How do I change the way vim autocompletes commands?

I use the :split in vim all the time, I however neveer uses :spelldump or :spell* in general.
Is there any way to make :split be the first commmand to appear when autocompleting on :sp ?
Like I said in the comment you don't need to autocomplete for this particular use case, :sp will do the trick. If you enter part of a builtin command that is ambiguous, Vim prefers one command over the other:
:s could be :substitute, :split, :spelldump, etc., but for Vim it is :s[ubstitute]
:sp could be :split, :spelldump, :sprevious, etc., but for Vim it is :sp[lit]
In the help this is indicated with square brackets around the optional part of the command just as is shown above.
To answer the general question: I don't think you can change the way Vim autocompletes commands. You can define your own shorter command (which must be uppercase), e.g. :command! S split. Or you could define a mapping, e.g. :nnoremap \s :split<CR>. Finally, you could use a builtin normal mode command, which for this particular use case is simply CtrlW followed by S.

VIM: Know which command executed when a key pressed

How do I know which command will be executed when I press a key, for example <Leader>c?
To see mappings use:
:verbose map <leader>c
Replace map by the corresponding imap, cmap, etc., as needed.
For Vim's built-in commands you'll need to use the help:
:help gq
See :help context for pointers.
Sometimes if map <keys> is not enough you may use one of the following:
:debug normal <keys><CR>: for normal, visual, select, operator-pending and insert/replace/virtual replace modes but not for ex/command-line mode. You will have to precede <keys> with something that enters target mode.
:set verbosefile=/tmp/verbose.log verbose=15<CR><keys>:set verbose=0<CR>: for all modes it will procude a log of all commands executed in file /tmp/verbose.log. You will see errors if there is a recursive structure somewhere.
Start vim with vim -s <(echo '<keys>') -D. It will enter debug mode immediately after vim starts, but you will have to skip all initializations manually.
These are all advanced debugging features and they are very time-consuming, but they may help where something more simple cannot.

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

Use last arguments from vim's :make command

I have a one key mapping to build my project.
noremap <F5> :make<CR>
This works great. However I sometimes am building a only a piece of the project. In this case I use the command :make smaller_part to build just that piece. I'd also like a one key mapping for this use case as well.
noremap <S-F5> :make last_arguments()<CR>
Is this possible? A last_arguments() function isn't required. It's just how I imagine the solution would look. The important part is I hit one key and it runs :make with the arguments that I gave it last time.
I use
map <f2> :wa<cr>:Make <Up>
to run make with the last arguments
by the way
command -nargs=* Make write | make <args> | cwindow 6
is the Make.
I don't know whether you can programmatically retrieve the last line from the command history, or specific arguments on it. I expect you can, but I don't know how to do it offhand.
But what are the constraints here? If you'll allow your initial invocation of make to call a function you've defined, say :MyMake(smaller_part), then that can save the smaller_part in a variable and you can define a Remake() function that will call make on the target saved in that variable.
Is that solution acceptable to you? Or must the original invocation be of the form :make smaller_part?
What if you wrap the :make command in a couple commands of your own? One command runs make with whatever argument you supplied (possibly none). It also stores the argument in a variable. Then you map this command to <F5>. The other command runs make with the argument stored in your variable (again, if any). You map this command to <S-F5>. I think the vim command for defining your own commands like this is Command.

Resources