Automatically expand fold when going to a line number - vim

Is there a way to unfold code when going to a line number? For instance I type :35 where line 35 is folded, then I have to unfold that section manually to actually get to that line. I would like to type :35and have that code then unfolded automatically and my cursor put on line 35 without any further key presses.

If you use the 35G command instead of :35, you can achieve this with the following mapping:
"[count]G Also open fold under cursor when supplying [count] (i.e.
" jumping to a particular line, not the end of the
" buffer). Use [count]|gg| if you don't want this.
nnoremap <expr> G (v:count ? 'Gzv' : 'G')
For :35 itself, this would be hard to achieve. You would have to intercept the <CR> via a :cmap <expr>, check the typed command via getcmdtype() and getcmdline(), and, if it's a number, manipulate the command, i.e. append normal! zv to it; like this:
cmap <expr> <CR> getcmdtype() == ':' && getcmdline() =~ '^\d\+$' ? 'normal! zv<CR>' : '<CR>'

zv. From :help zv:
View cursor line: Open just enough folds to make the line in
which the cursor is located not folded.
While this command could probably be triggered automatically in some way, I have not come across it yet. Using the command as-is has served me well, though.

Define a new command mapping. In this example, I chose \gz:
:nmap \gz gg<Bar>zO

Related

Is it possible create a shortcut on vim to replace multiple times on a file?

I would like create a shortcut on vim to replace multiple times on a file, this a tool that I use several time.
Example of tool:
:%s/this.props/otherProps/gc
This command will replace all this.props to otherProps and ask to confirm
But I'm trying to convert this command in a shortcut like the example below:
// on .vimrc
noremap <leader>F :%s/$1/$2/gc
So in this case, I would every time a press <leader> + F, I type the first word, and after I press tab and type second word and after press enter.
I've put in the $1 and $2 as an attempt, but it doesn't work.
I tried to search some document about this, but I didn't find anything, maybe have some word more specific about that I don't know yet.
You could use a custom function by adding something like the following to your .vimrc:
function! Replace()
call inputsave()
let pattern = input('Enter pattern:')
let replacement = input('Enter replacement:')
call inputrestore()
execute '%s/'.pattern.'/'.replacement.'/gc'
endfunction
nnoremap <leader>f :call Replace()<cr>
With this everytime you hit <leader>f the function is called. Which is then gonna ask you first for a pattern, then for a replacement and is then gonna execute the substitute command.
Whilst this doesn't do exactly what you asked for, it does get pretty close.
noremap <leader>F :%s//gc<LEFT><LEFT><LEFT>
This will type out the command noremap <leader>F :%s//gc but leave your cursor between the 2 slashes, ready to type in the stuff you want to find and replace.
So now you can just hit <leader>F and start typing this.props/otherprops and then hit enter. It does exactly what you want but instead of pressing tab you press /
cnoreabbrev <expr> esr getcmdtype() == ":" && getcmdline() == 'esr' ? '%s:\<end\>: & /*}*/:g' : 'esr'
This replaces end to end: /*}*/
You can add this to gvimrc; whenever :esr is typed, the above will be executed.

Why isn't this Vim mapping working?

noremap :hsp :botright new
noremap :vsp :botright vnew
"Not an editor command: hsp"
I'm probably googling the wrong thing, but I can't find many results on aliasing vim commands. I can find tons of info about mapping keys to commands like my one for tabs:
noremap <C-t> :tabnew<CR>
But can't find commands mapped to other commands.
What you're doing is simulating a command with a mapping. You're saying that when you press the 4 keys :hsv in normal mode, it should type out the keys :botright new (which would need a <CR> to run, as others have said), but it's not actually making the command hsv. You could make an actual command with a user command (:h user-commands). These must start with a capital letter, though.
:command Hsp botright new
:command Vsp botright vnew
Now you can type :Hsp and hit enter to run the command botright new.
Did you try command abbreviation?
ca hsp botright new
ca vsp botright vnew
You will have to initialize the expansion of the abbreviation by hitting the space key afterwards. Depending on the global vim configuration, expansion also happens automatically just when enter is pressed.
with your same mapping, I cannot get the Not an editor command: hsp error message with my vim (v7.4).
Your mapping works fine, but you don't have <cr> at the end, so when you press :hsp in normal mode, your mapping will switch to commandline mode, and put the mapped command there, without executing it. You have to manually press Enter.
#XZS's answer works, but keep in mind that it is an abbreviation(ab), not a mapping. ab is not command aliases, it is not exactly same as mapping. For example, you have to press another key (like space) after hsp to trigger the ab. also, you cannot ab some special keys, this would be another limitation of ab.
There is c(nore)map for command mapping.
e.g. you could have:
cnoremap hsp botright new
with above line, as same as your original one, you have to manually press Enter, if you want it to be executed, you need add <CR> at the end of the line.
I think if I do this, I would create mapping.
Creating command alias can be tricky:
Using a simple cabbrev and/or cmap will cause expansions and mappings to fire in unexpected places like during searches with / and in the middle of filenames.
cmap's will have a visible delay in outputting to the screen which is why cabbrev is often used.
However there are a few ways to create a proper alias:
Create a command via :command.
e.g. command W w
command's first letter must be a uppercase letter
must supply -nargs, -bar, -complete, and -range options according to the needs of your alias
Expression :cabbrev to guard the abbreviation from expanding in in proper places.
expression mapping use the <expr> option
verify getcmdtype() is equal to :
verify the abbreviation is at the beginning of command line via getcmdline() or getcmdpos()
e.g. cnoreabbrev <expr> W getcmdtype() == ':' && getcmdline() ==# 'W' ? 'w' : 'W'
Use :Alias via the cmdalias.vim plugin by Hari Krishna Dara
e.g. Alias W w
uses an expression cabbrev under the covers similar to the technique above

Vim abbreviation also applies to search (bug?)

I think I just found a Vim bug, but before bothering Bram Moolenaar about it, I thought I'd check here if my understanding of Vim command syntax is right.
In my .vimrc, I have
cnoreabbrev W w
cnoreabbrev Q q
because I tend to hold shift depressed when typing :w or :q, giving :W or :Q. However, when I now try to search for W or Q with /W, ?Q, etc., Vim finds occurrences of w or q instead. I find this surprising since I thought I had only abbreviated commands, not a search strings. Removing the two lines from my .vimrc gives the desired behavior.
Is this a bug or a feature of cnoreabbrev? It occurs both in the Debian-packaged Vim 7.3.923 and in the current Mercurial tip.
Command line abbreviations are notorious for causing subtle bugs that the user did not intend. The type of aliases that you are trying to create should probably be converted to commands.
command W w
command Q q
I leave the completion, bang arguments, and range arguments as an exercise for the reader.
However if you really do want to use cnoreabbrev you need to do it carefully. I typically make an expression abbreviation that checks getcmdtype() and checks the value of the command line as well via getcmdline(). Example below
cnoreabbrev <expr> W getcmdtype() == ':' && getcmdline() ==# 'W' ? 'w' : 'W'
If you don't want to create the logic yourself you can use a plugin by Hari Krishna Dara call cmdalias.
For more help see:
:h Command-line-mode
:h :command
:h :map-expression
:h getcmdtype()
:h getcmdline()
I won't say it is bug, it is a ..... feature. :D
what you did is create an ab, only in command-line mode.
/ (search) will bring you in command-line mode too. that's why the ab worked there as well.
:h vim-modes
you can see:
Command-line mode In Command-line mode (also called Cmdline mode) you
Cmdline mode can enter one line of text at the bottom of the
window. This is for the Ex commands, ":", the pattern
search commands, "?" and "/", and the filter command,
"!".
so
This is for the Ex commands, ":", the pattern
search commands, "?" and "/", and the filter command,
"!".
Feature.
If you hit space after ?Q you will see is changed to ?q
My way of fixing it is actually just to define a user command. (Since it starts with a capital anyways it works)
command! Q q
command! W w

Vim open file with h and l

So I have the following lines in my vimrc to scroll through autocompletion using jk.
" Making autocompletion work with jk
inoremap <expr> j ((pumvisible())?("\<C-n>"):("j"))
inoremap <expr> k ((pumvisible())?("\<C-p>"):("k"))
I was wondering if there would be a way to scroll through :tabe<Tab> suggestions using hand l? That's what would seem the most natural to me, however I haven't been able to find anything on how to do that.
When using command line completion, whether you use wildmenu or not and whatever value you have set for wildmode, your cursor stays in the command line and whatever printable character you hit is inserted including, of course, h and l.
With that in mind, do you really think it would be wise to abandon the ability to insert h and l in the command line?
If you don't like <Tab> you could try the wildchar option but you won't be able to get rid of or replace <C-n>/<C-p> and the arrows.
Also, command line completion is a generic feature that is not limited to :tabe. :tabe is a red herring, here.
To remap h and l looks weird to me. They are really usefull, at least you need it to write, type commands etc...
If you want an easy autocompletion tips you should add these lines in your vimrc :
set wildmenu
set wildmode =list:longest,list:full
And then add the SuperTab function, it allows you to autocomplete with Tab and navigate into the menu with Tab also. Here is the code :
imap <Tab> <C-R>=SuperTab()<CR>
function! SuperTab()
if (strpart(getline('.'),col('.')-2,1)=~'^\W\?$')
return "\<Tab>"
else
return "\<C-n>"
endif
endfunction
Hope it helps !

How to make an horizontal ruler with vimscript?

i'm trying to do a command that fills up the current line with # , then goes to the begining and rewrites with the date and time, then o, this is my attempt:
:nnoremap <F6><Home>
set count = 0
normal i
while count <= columns
normal #
set count += 1
endwhile
<Home>R =strftime("%c")<CR>
normal o
the result of pressing F6 should be somehting like:
Date and time######################################################################
but yeah this is my first attempt at extending vim so please help me understand how to make this allright.
The right-hand side of a mapping is basically the same as if you typed the commands. This allows you to gradually move from repeatedly typing something to recording a macro (#q), to finally making a permanent mapping.
Here's a somewhat literal translation of your attempt:
:nnoremap <F6> 80I#<Esc>0R<C-r>=strftime("%c")<CR><Esc>o
It uses a fixed width of 80. If you want something more dynamic (like the value of 'textwidth' when it's > 0), you have to move from direct execution to programmatic interpolation via :execute, like this:
:nnoremap <F6> :execute 'normal' (&textwidth > 0 ? &textwidth : 80) . "I#\<lt>Esc>"<CR>0R<C-r>=strftime("%c")<CR><Esc>o
As you can see, this is already way more cryptic, with a mixture of Ex commands and :normal mode, quoting, etc.
The final step is a fully configurable and reusable plugin. Only for those, with elaborate error handling and stuff, you'd typically use separate :function definitions, which are then just called from your mapping:
function! s:InsertSeparator()
...
endfunction
nnoremap <silent> <F6> :call <SID>InsertSeparator()<CR>
You can use printf in vimscript.
:nnoremap <F6> I<C-r>=substitute(printf("%-80s", strftime("%c")), '\(\s\)\#<=\s', '#', 'g')<CR><Esc>o

Resources