I've got the following vimscript function:
function! WindowCommand(cmd)
execute a:cmd
if !g:golden_ratio_enabled
normal <C-w>=
endif
endfunction
And I use it like so:
map <space>w/ :call WindowCommand(':vs')<cr>
It's supposed to equalize the windows, but only if g:golden_ratio_enabled is 0, otherwise it should do nothing.
It doesn't work, though, and I'm not sure why, because the following DOES work:
map <space>w/ :vs<cr><C-w>=
What am I doing wrong here?
There are a couple fixes. Thankfully, the fix is really simple
For whatever reason, normal <C-w>foo does not work; You must use wincmd instead. From :h wincmd
*:winc* *:wincmd*
These commands can also be executed with ":wincmd":
:[count]winc[md] {arg}
Like executing CTRL-W [count] {arg}. Example: >
:wincmd j
Moves to the window below the current one.
This command is useful when a Normal mode cannot be used (for
the |CursorHold| autocommand event). Or when a Normal mode
command is inconvenient.
The count can also be a window number. Example: >
:exe nr . "wincmd w"
This goes to window "nr".
So in this case, you should do
wincmd =
Alternatively, you could enter a literal <C-w> character, by typing <C-v><C-w>. In your vim session, this character will be displayed as ^W.
To execute actions with <notation>, use instead:
:exe "normal \<notation>"
I use it a lot to debug mappings.
But in this case, prefer indeed wincmd.
Related
There might be a simple solution for this. I couldn't find any solution to it (I might be searching with wrong context)
Here is my requirement.
I wrote the below key mapping in vimrc. It should print the line "Hello user_name." n times, where n and user_name are the user input once the key is pressed.
autocmd FileType ruby nnoremap <expr> <C-h> :call FuncPrnt(<-syntax to pass input from user->)
function! FuncPrnt(count, uname)
let c=a:count
let i=0
while i<c
call append(line("."), "Hello ".a:uname.".")
let i+=1
endwhile
endfunction
On Pressing the key user enters 3 and 'Ironman'. The output would be like
Hello Ironman.
Hello Ironman.
Hello Ironman.
Thanks in advance
A simpler approach is to just use a non-<expr> mapping to prepare the Ex command without executing it:
nnoremap <C-h> :call FuncPrnt(,"")<left><left><left><left>
If you associate that with a filetype (such as "ruby" in your case), make sure you create a local mapping using <buffer>. Otherwise the mapping will be global and will work on every buffer and not only those with Ruby source files.
If you use an autocmd in your vimrc, make sure you wrap it in an augroup to prevent getting duplicated commands if you reload your vimrc.
Alternatively, you can add filetype mappings for Ruby in a file ~/.vim/ftplugin/ruby.vim which gets automatically loaded by Vim whenever a file of type Ruby is loaded. (That way you don't need to use explicit autocmds, Vim will take care of those details on your behalf.)
Got the answer. Just in case someone else is searching for similar solution
autocmd FileType ruby nnoremap <expr> <C-h> input("", ":call FuncPrnt(,\"\")<left><left><left><left>")
will print the command and waits for the user to edit. Once the user edits and enters it is executed
Thinking outside of the box a little bit (questioning the premise), perhaps the best in this case is to define a user-defined command instead of a mapping.
You can define one here with:
command! -buffer -bar -count=1 -nargs=1 FuncPrnt
\ call FuncPrnt(<count>, <q-args>)
That way you can use it with:
:3FuncPrnt Ironman
If you omit the count, 1 will be used. (You can pick a different default as the argument to -count=N.)
You can use Tab completion for FuncPrnt, so perhaps :3Fu<Tab> or even :3F<Tab> might be enough to complete the command.
This might end up being quicker or more convenient to type than <C-H>3<right><right>, since it doesn't involve moving your hand to the arrow keys.
I'm looking to change the following vim command so that after entering the :%s/temp123//g part it will put me into insert mode between the \begin and \end tags.
inoremap \\beg \begin{temp123}<enter><enter>\end{temp123}<enter><esc>:%s/temp123//g<left><left>
I have been able to use :startinsert to get into go into insert mode after entering the search/replace command but I am not able to place the cursor between the \begin and \end tags.
Any help/solutions/improvements would be appreciated.
TL;DR: can't.
:star[tinsert][!] Start Insert mode just after executing this command.
Works like typing "i" in Normal mode. When the ! is
included it works like "A", append to the line.
Otherwise insertion starts at the cursor position.
Note that when using this command in a function or
script, the insertion only starts after the function
or script is finished.
This command does not work from :normal.
I was trying to get the following line working:
nnoremap <MiddleMouse> :set paste<cr>:startinsert<MiddleMouse><esc>
What this means is that all of my commands that I put after :startinsert instead run immediately before :startinsert and then :startinsert runs and changes the mode to insert (Note: this appears to hold true for using i instead of :startinsert as well).
My next step was to try to make a nested function, where I had one function that calls another function, and the second function runs :startinsert and then returns to the first function, which then completes the paste:
function! Paste()
call InsertMode()<cr>
:set paste<cr>
<S-Insert>
:set nopaste<cr>
<esc>
endfunction
function! InsertMode()
:startinsert<cr>
endfunction
nnoremap <MiddleMouse> call Paste()<cr>
But this did not work either. I also tried using the "+p and "*p registers without :startinsert with nnoremap <MiddleMouse> :set paste<cr>"+p:set nopaste<cr>, but this again just pastes directly as if I were typing it in, it does not enter insert mode first. I am willing to believe this would work on a version of Vim compiled with +clipboard, but that is not the version I have. Link to my original question and answer
Yep, you're looking for an interactive substitution, but :s/new/old/gc doesn't let you edit each match. For this kind of work, switch to the gn command + . recipe:
First search for {temp123} (or whatever you wish to replace) with /
Then press cgn to change the visually selected next match
Once done, go back to normal mode to commit your edits.
If the next edit is the same as the last, press only . otherwise cgn
Rise and repeat.
For more ideas, see this vimcast: gn command
This is the solution I am now using.
function TexBegin()
let currline = line(".")
call inputsave()
let tagname = input("enter tag name: ")
call inputrestore()
call setline(currline, "\\begin{" . tagname . " }")
normal o
normal o
call setline(currline + 2, "\\end{" . tagname . "}")
normal l
startinsert
normal o<Esc>
endfunction
inoremap \\beg <Esc>:call TexBegin()<CR>
Gived this script (packages suggestion was simplified, original takes care of <cword>)
function! CompleteImport()
let packages = ['java.util.Vector','java.lang.String']
call complete(col('.'),packages)
return ''
endfunction
inoremap <F8> import <C-R>=CompleteImport()<CR>
while on insert mode you can add an import and choose between suggested packages pressing F8
But I want to be enable to reach that popup selection from normal mode
function! InsertImport()
exe "normal iimport \<C-R>=CompleteImport()\<CR>"
"this commented line would work too
"exe "normal i\<F8>"
endfunction
map <Leader>ji :call InsertImport()<CR>
so from normal mode ,ji (stands for java import) add an import to word under cursor if it is found
(Move to right position is not a problem so I ommit here)
By now ,ji adds first suggestion from popup and exists insert mode
I have tried :startinsert but no luck.
see on http://vimdoc.sourceforge.net/htmldoc/eval.html#:execute there is a suggested code:
:execute "normal ixxx\<Esc>"
but that final Esc doesn't matter at all (for my vim install at least) This do exactly the same for me:
:execute "normal ixxx"
I would think this is not possible if I haven't found that on docs. So, it's possible to stay on a popup calling from a function?
Other interested docs:
http://vimdoc.sourceforge.net/htmldoc/various.html#:normal
http://vimdoc.sourceforge.net/htmldoc/insert.html#:startinsert
:startinsert usually is the right approach, but it indeed gives control back to the user, so you cannot automatically trigger the completion.
Through the feedkeys() function, you can send arbitrary keys "as if typed". This allows you to start insert mode and trigger the completion:
function! InsertImport()
call feedkeys("iimport \<C-R>=CompleteImport()\<CR>", 't')
endfunction
nnoremap <Leader>ji :call InsertImport()<CR>
PS: You should use :noremap for the normal mode mapping, too; it makes the mapping immune to remapping and recursion.
Is there a command or function like :execute that allows you to send text to the Vim cmdline but that doesn't actually execute it? I want to have the cursor left at the end of the cmdline. I've been going through the help docs for half an hour, can't find anything.
It depends on how that gets triggered. If it's through a mapping, you can simply use :help :map-expr:
fun! MyText()
return (localtime() % 2 ? ':echo ' : ':echomsg ')
endfun
:nnoremap <expr> <Leader>e MyText()
Else (i.e. through a custom command or by :autocmd), you have to use the feedkeys() function to insert the typed characters into Vim's input event loop:
:command! MyText call feedkeys(MyText(), 'n')
You cannot just use :normal, because that assumes a full command, and will abort if it's incomplete.
I came to an idea that <C-a> in Vim's normal mode should not only increase numbers but toggle booleans. It makes sense if you consider true and false as integers modulo 2.
So, I downloaded an excellent script to do the hairy work and wrote a new definition for <C-a>:
fun! NewCA()
let cw = tolower(expand("<cword>"))
if cw == "true" || cw == "false"
ToggleWord
else
" run the built-in <C-a>
execute "normal \<C-a>"
endif
endfun
command! NewCA :call NewCA()
nnoremap <C-a> :NewCA<cr>
But as it happens, nnoremap doesn't go as far as to check inside functions. I get recursive behaviour if my cursor is not on words true or false.
In this point I swear a lot, why didn't Bram go pick an excellent idea from Emacs, that everything should be functions and key bindings freely setable. Then I just could check the function for <C-a> and call it in that function. But no, I can't find such a function, and the execute "normal foo" phrases seem to be the Vim idiom.
Any suggestions on how I could make <C-a> work such that
Toggle booleans when the cursor is over a word true or false
Fall back to built-in <C-a> behaviour otherwise
Help appreciated!
change
execute "normal \<C-a>" to:
normal! ^A
you can get ^A by running <C-v><C-a> in normal mode
the "!" at the end of normal say "use default mapping"
From :help :normal
:norm[al][!] {commands}
...
If the [!] is given, mappings will not be used.
....
Also defining a command is not needed, you can directly
nnoremap <C-a> :call NewCA()