Whenever I am browsing folded code in vim and press the l key I want it to open that fold recursively. For that I did the following: nmap l lzO. Which worked ok, apart from the fact of getting a E490: No fold found whenever I would press l not in a fold. I used that an excuse to learn about Vimscript and write a function for that and avoid the error.
Now, I am missing the part of how can I call a vim command like l or lzO from inside a function?
function! OpenFoldOrNot()
if foldclosed(line(".")) == -1
echo "just l"
l # TODO
else
echo "open fold"
lzO # TODO
endif
endfunction
nmap l :call OpenFoldOrNot()<CR>
Try the normal command. For this case you will need normal! to avoid recursive execution of your function.
You could try the following, using the normal command (my vimscript is very rusty):
function! OpenFoldOrNot()
if foldclosed(line(".")) == -1
normal! l
else
normal! lzO
endif
endfunction
nmap l :call OpenFoldOrNot()<CR>
Alternatively you can use a map-expression to make this kind of job easier.
nnoremap <expr> l foldclosed(line(".")) == -1 ? 'l' : 'lzO'
In a map expression the right hand side, {rhs}, of the mapping is a VimScript expression. This is evaluated to obtain what to execute. In your case it is used to determine if the mapping calls l or lz0.
For more help see:
:h :map-expression
Related
I want to map <M-o> to quickly look up buflist from command-mode.
Here's an example normal-mode mapping:
nnoremap <M-o> :ls<CR>
Here's an attempt to do the same for command mode using execute():
cnoremap <M-o> <C-r>=execute(':ls')<CR>
This however simply appends whitespace-separated :ls results to the command line, with no side effect of the :ls table actually showing.
Is there a way to execute a command without leaving command-mode?
Update:
Closest I've come to cracking this using Vimscript is the following:
function! RunCmdFromCmdline(cmd)
let l:cmd_line = getcmdline()
echo execute(a:cmd)
return l:cmd_line
endfunction
cnoremap <M-o> <C-\>eRunCmdFromCmdline(':ls')<CR>
The echo makes it so the results of a:cmd do pop on the screen, however in invisible font. I tried playing with :redraw <bar> in different combinations with no success.
Exiting from the command mode from within a <C-r>= or <C-\>e prompt does not seem possible.
You can save the contents of the current command line in a register, then run ls and paste the contents of the register:
cnoremap <esc>o <home>let #x="<end>"<cr>:ls<cr>:<c-r>x
So if command line looks like this:
:echo 'some'
type <M-o> to get:
:ls
1 %a + "filename" line 1
:echo 'some'
This works. It uses global variables, but arguably this is an acceptable use for them, since there's only a single command-line you can be in at a time.
function! SaveCmdline()
let g:save_cmdline = getcmdline()
let g:save_cmdpos = getcmdpos()
return ''
endfunction
function! RestoreCmdline()
call setcmdpos(g:save_cmdpos)
return g:save_cmdline
endfunction
cnoremap <M-o> <C-\>eSaveCmdline()<CR>ls<CR>:<C-\>eRestoreCmdline()<CR>
This works with whatever quotes or unfinished syntax you have in your command-line, restores the full command-line and the cursor to the position it was before running the command, doesn't mess with any registers (only touches the two global variables) and doesn't mess with command-line history either (see q: command for history.)
It does have one tiny bug, in that cnoremap actually also works when you're typing a search expression (after / or ?) among a few other sub-modes (see getcmdtype() for a list of those.) If you use the mapping there, it will search for "ls" and then restore your search term as an Ex command, oops...
You can probably use getcmdtype() to detect that and possibly only perform the actions while you're typing an Ex command and not in the other modes.
UPDATE: This fixes the last part, only executing the command while in the Ex command-line, not in search or other context. It also makes the interjected command parameterizable.
function! CmdlineExecute(cmd)
if getcmdtype() != ':'
return ''
endif
return "\<C-\>eSaveCmdline()\r".a:cmd.
\ "\r:\<C-\>eRestoreCmdline()\r"
endfunction
cnoremap <expr> <M-o> CmdlineExecute('ls')
(Note this still needs the definition of the two functions above.)
Does anyone know why I'm getting the following error? I'm mapping the following function
function! ToggleCompileErrors()
:if w:syntastic_is_open == 1
:call SyntasticReset()<CR>
let w:syntastic_is_open = 0
:else
:call SyntasticCheck()<CR>
let w:syntastic_is_open = 1
:endif
endfunction
With this command
command ToggleCompileErrors :call ToggleCompileErrors()
and it is getting called by the following keymapping
nnoremap <Leader>b :ToggleCompileErrors<CR>
And I don't know if it makes a difference but I am using neovim 0.2.2
Watch your modes. That <CR> :help key-notation is necessary for mappings, but not inside functions, which use Ex commands.
Likewise, you don't need to prefix commands inside a function with : (and this is rather odd here, especially because you're not even consistent about it). : is a normal mode command that enters command-line mode. As commands in a function already are Ex commands, the : is not needed.
I would like Vim to place my cursor in the middle of screen after search. I have achieved for *, #, n and N commands with the following lines in .vimrc
nmap * *zz
nmap # #zz
nmap n nzz
nmap N Nzz
My question is: how to map / and ? the same way? I.e. I would like to position cursor after some text has been found using
/some-text-to-find-forward
?some-text-to-find-backward
Edit: Threw away my initial answer as it was too much of a kludge. Here's a much better solution.
function! CenterSearch()
let cmdtype = getcmdtype()
if cmdtype == '/' || cmdtype == '?'
return "\<enter>zz"
endif
return "\<enter>"
endfunction
cnoremap <silent> <expr> <enter> CenterSearch()
The way this works is to remap Enter in command-line-mode to a custom expression.
The function performs the current search followed by zz if the command-line is currently in a search. Otherwise it just executes whatever command was being done.
It's not very pretty, but
:nnoremap / :execute "normal! /\<lt>cr>zz"<c-left><right>
will get the job done. (Puts an :execute "normal! /" command on the commandline, then adds a <cr>zz to the end to it so that you automatically zz when you issue the command. The final <c-left><right> just steps into the search pattern at the right spot
Solution from Randy Morris but as a oneliner:
cnoremap <silent><expr> <enter> index(['/', '?'], getcmdtype()) >= 0 ? '<enter>zz' : '<enter>'
I want to use registers value in command line and in function in GVIM.
More specificaly my goal is to ease the on-the-fly highlithing of my log file. I want to be able to hightlight by a simple command the selected string like the * touch do.
Currently I have these line in my vimrc
hi Hi1 guifg=#FFD000
hi Hi2 guifg=#FA0020
hi Hi3 guifg=#A5BB00
To highlith I write in the command line:
:syntax match Hi1 /MON_STRING/
and I obtain what I want. I would like to have a command like
noremap ,H1 :syntax math Hi1 "0
to do the same more easyly but I haven't find the right way to write "0
Any idea?
EDIT =>
Thanks to the answer I create the function that I was looking for:
let g:hicounter = 0
function TT(incr)
if a:incr == 1
let g:hicounter = g:hicounter + 1
let g:hicounter = g:hicounter % 18
endif
:exec 'syntax match Hi' . g:hicounter .' /'.#/.'/'
:echo "falue de incr a:incr " . a:incr . " :let g:hicounter ="
endfunction
noremap <F3> *#:call TT(1)<CR>
noremap <s-F3> *#:call TT(0)<CR>
use execute
:exec 'your command'.#x
x is the reg
. concatenating the cmd strings
Your approach uses :syntax match; that can interfere with the existing syntax (so sometimes, your highlighting won't match on existing syntax, or it prevents the existing syntax to properly highlight the file). For a more robust highlighting, :match / matchadd() is better (but more complex to manage).
If you're willing to install a plugin, my Mark plugin provides this functionality. (The plugin page has links to alternative plugins.)
As we know that you can't enter insert mode by
:exec "normal [iIaAs]"
The only way I know to enter the insert mode from colon command is
:startinsert[!]
While the :startinsert performs like 'i' and :startinsert! like 'A'. But how can I get 'a'?
You can't use
:exec "normal l"
:startinsert
because it doesn't work at the end of line.
does feedkeys function help ?
e.g.
:call feedkeys('a','n')
This snippet:
function! Append()
startinsert
normal! l
endfunction
nmap <F6> :call Append()<CR>
makes <F6> work like a.
Outside of a script, you must do:
:startinsert
<C-o>
:normal l
Note that execute is necessary only if you do some interpolation or concatenation in the command you want to execute.
execute "normal a"
is pointless but
execute "normal a" . my_variable
is correct.