How can I delete empty lines in motion in Vim - vim

I know how to delete blank lines with commands.
We may visually select the text block first, and then run commands like
s/^$/d to delete all blank lines or %s/^\(\s*\n\)\+/\r to keep only one blank lines.
Can I perform the above using motion, so that I can just press some keys to perform the "delete-motion" without having to enter command-line mode?

Creating a new operator for this is a good idea, but it can be tough to get right.
The operator-user plugin makes that task easy.
Once you have installed operator-user, all you need to do is add two lines to your vimrc, one to define the operator, and one to define your personal mapping to it:
call operator#user#define_ex_command('delete-blanks', 'g/^$/d')
map _ <Plug>(operator-delete-blanks)
This creates a new operator _. Change it to whatever you like best.
Now you can do _3} or _G or _23k to delete the blank lines contained in the motion. Text objects _a}, doubling of the operator 4__, and Visual mode V7j_ are all also supported, as befits a proper operator.

You could use operatorfunc. For example:
Define a function like this in your .vimrc:
function! DeleteEmptyLines(type)
if a:type == 'line'
silent execute ".,'\"g/^$/d"
endif
endfunction
And a mapping:
nnoremap <silent> ,d :set operatorfunc=DeleteEmptyLines<CR>m"g#
,d performs now just like an operator and accepts a (line-based) motion. You can, for example, insert ,d5j or ,dG in normal mode to delete empty lines in the next 5 lines or to the end of file.
You can find more information on how to extend this functionality here:
http://learnvimscriptthehardway.stevelosh.com/chapters/33.html
and of course::h operatorfunc and :h map-operator.
From :h map-operator:
"An operator is used before a {motion} command. To define your own operator
you must create mapping that first sets the operatorfunc option and then
invoke the g# operator. After the user types the {motion} command the
specified function will be called."

well, using motions I don't think you can only delete blank lines.
But you can do it using a mapping:
:nmap <Leader>db :g/^$/d<CR>
The motions help you move one word, one paragraph away... And before the motion you use an operator (d, c...).
So what you'd want is to create a new operator that deletes blank lines within the given motion (or selection). What I gave you is close to that, but you'd have to invent a new operator (and I don't think there's many unbound keys left).
Other vimmers may correct me, but I think the easiest way to create such operators would be to define a map for each motion and bind it to a function.

There isn't a motion that can combine with a delete such that it only deletes blank lines. A motion denotes all the text between the initial and final position, without any gaps. That includes motions which search using regular expressions.

Related

How do I map Vim colon search and replace command to work just with visual selection?

Sometimes I want to replace some text in multiple lines but not in the whole line, so I toggle visual mode on and highlight the text I want to replace. But then, I need to add this annoying \%V that I always forget for it to replace the text just in the selection and not in the whole line
:'<, '>s/\%Vold/new/g
Is there a way to map the normal replace command
:'<, '>s/old/new/g
To the one shown above so that I don't need to remember that V every time?
Thank you
I tried using cmap command in the vimrc file in the following way:
cmap '<, '>s/* '<, '>s/\%V*
But this of course doesn't work, because instead of the asterisk I should input the text I want to search and replace to end the search and replace command.
There are three basic parts to a mapping:
the mapping command,
the "left-hand side" (LHS),
and the "right-hand side" (RHS).
The LHS is the key sequence/combination that you want to press and the RHS is a different key sequence that you want Vim to "press" instead of those in the LHS. You "map" one key sequence to another.
The RHS is, fundamentally, a macro: a sequence of keystrokes, "just" like if you pressed them yourself but without any delay between them. So, the RHS is really just a bunch of keystrokes you are tired of making over and over again.
The main use of mappings is to reduce repetitiveness. You figure that you often press the imaginary sequence sdlusdrosydtsodsd and you map it all to <F5> to be more efficient.
In this case…
The current mode is visual mode so the mapping has to be a visual mode mapping.
This makes :xmap or :xnoremap the proper mapping command. Let's make it :xnoremap.
The repetitive key sequence you want to abstract away is:
:s/\%V
That's your RHS.
(Note that the range '<,'> is automatically inserted for you so it can be ignored.)
The key sequence you want to press instead is, let's say… <F5>.
That's your LHS.
Now that you have your mapping command, your LHS, and your RHS, building the mapping is extremely easy:
:xnoremap <F5> :s/\%V

Move to the last character of previous line vim

I have started using vim recently and was wondering if there's any keyboard shortcut to move the the last character of previous line( line number l-1 if I am currently on line number l) ?
One of the ways is to use the up arrow to move to the same column of previous line and then use $ to move to the end of the line.
I am looking for some shortcut to do that in one command.
UPDATE:
Here's also another solution to move to the beginning of the next line / the end of the previous line without the need to set any mappings. Add these three to your .vimrc:
set whichwrap+=<,h
set whichwrap+=>,l
set whichwrap+=[,]
(Credit to: Kevin H. Lin and garyjohn)
Original Answer:
I've not memorized all Vim shortcut combinations, so there might be one shortcut for what you're asking for, but I usually define a mapping whenever I need something I don't know how to do.
For what you need, you can simply define it with this:
nnoremap <S-L> <Up><S-4>
Just add it to your ~/.vimrc(if this file doesn't exist yet, create it yourself), then restart vim. Then the next time you open up your Vim, the "Shift-L" shortcut will do the job.
You can go straight into the insert mode as well and append characters after the last character of the previous line with this rule instead:
nnoremap <S-L> <Up><S-A>
Also in case you don't understand the structure of the above rules, you can read more about it here:
Understand Vim Mappings and Create Your Own Shortcuts.
There is a corner case: If your cursor is on the first line, pressing this mapping should not move the cursor.
Therefore, we can use the <expr> mapping:
nnoremap <expr> <F6> line('.')==1?'\<F6>':'k$'
In the example above, I used <F6>, you can choose the short-cut key you like.

Using placeholders in vim

Given a vim document with multiple occurrences of a specific placeholder, say <%%>, I want to be able to jump to the next placeholder from the beginning of the document: More explicitly, if the document is given by
$\frac{<%%>}{<%%>}$
I want to press a key such that the first placeholder gets removed, i.e. we have
$\frac{}{<%%>}$
where the cursor is at the position of the placeholder and vim is in insert mode.
I'm aware of the vim-latex plugin which implements such a behaviour but only need this one feature. I tried to use the /-search of vim but didnt get the cursor position right.
Thanks in advance for any advice.
lh-brackets provides this feature -- actually vim-latex placeholder system has been inspired by lh-brackets one.
The idea to implement this feature, is:
to look for the pattern of the placeholder -- prefer search() to know whether something has been found: no selection shall be done otherwise
Actually doing it correctly may require a couple of calls to searchpair() to handle the case where the cursor is in the middle of the placeholder, see lh-brackets code as search(..., 'c') is not enough;
select this pattern -- v + movement 3<right> for instance
and finally either go into SELECT-mode (gh <c-g>) or remove the placeholder and go into insert mode (s)
If your placeholder pattern is exactly <%%>, it'll be quite simple to implement.
" I factorize common code without introducing the exact keybinding
" NB: we have to use the ancestor of map-<expr> as the later doesn't
" permit to move the cursor -> we execute the expression register: :h #=
" NB: As said earlier a correct implementation would require to call searchpair()
" twice in case the cursor is within a placeholder, see lh-brackets code
nnoremap <silent> <Plug>(jump-next) #=(search('<%%>') > 0 ? "v3l<c-g>" : '')<cr>
vmap <silent> <Plug>(jump-next) <c-\><c-n><Plug>(jump-next)
imap <silent> <Plug>(jump-next) <c-\><c-n><Plug>(jump-next)
" Tests shall be done in a real plugin before binding to the chosen shortcut: µ, <f3>, <c-j>, <tab>...
nmap <silent> µ <Plug>(jump-next)
vmap <silent> µ <Plug>(jump-next)
imap <silent> µ <Plug>(jump-next)
If sometimes it could become <%somestring%>, then I would definitively recommend using lh-brackets or any snippet engine that already takes care of this -- for instance, mu-template would permit to use your exact snippets/templates by changing locally the default placeholder characters with VimL: let s:marker_open = '<%' +
VimL: let s:marker_close = '%>' (I'm also maintaining mu-template which depends on lh-brackets).
NB: lh-brackets also provides surrounding (non intrusive), and bracket pairs insertion (can be deactivated: add :let g:cb_no_default_brackets = 1 in your .vimrc)
Using a macro might help.
In your example, use /<%%> to search for your placeholder. Then gg will take you at the beginning of the document.
Then start the macro with qa for instance. Go to the next occurrence of your placeholder with n. Then, ca< will remove the placeholder. C-o q will stop recording, while keeping you in insertion mode.
To go to and replace the next placeholder, just do #a (execute the macro stored in register a)
Does this mapping help?
:nmap %% /<%%><cr>ni
It executes a search (/<%%><cr>), repeats the search with n to skip the 1st placeholder and goes to the second. Then it switches (i) to Insert Mode.

vim cmap lhs only at the beginning

I have a mapping
:cnoremap ch call ShowHistoryMatching
The problem is that the ch characters expand to the right sentence in any case they are typed, no matter if at the beginning or later in the cmap input.
The problem is when I try to search for words in vim using / or ? e.g. for
/cache - it will be expanded using the mapping above.
How can I set the mapping ch to be extended only when it occurs at the beginning of the command?
cmap's are notoriously tricky because they often execute in the wrong context. Some better alternatives:
Use a normal mapping e.g. nnoremap <leader>ch :call ShowHistoryMatching()<cr>
Create a command e.g. command Ch call ShowHistoryMatching()
Use a the cmdalias.vim plugin
Use a more clever abbreviation as described in vim change :x function to delete buffer instead of save & quit post. Similar technique to cmdailias.vim.
Personally I would just create a new command.
You can use the getcmdpos() function to determine if you're at the beginning of the line or somewhere else. This technique can replace a built-in command using an abbreviation or you can adapt it for use in a mapping, possibly with an <expr> mapping.

VIM: Mappable (unused) shortcut letters?

I'm trying to create two mappings which are efficient for myself:
map X ddp
Which I'd use to delete and paste in one go.
map X "_dw
Which would delete a word without yanking into a register.
However I don't want to break any existing, useful shortcuts so I'm wondering what keys I could use - any suggestions? Am I being too uptidy?
vim help has a section :he map-which-keys
1.7 WHAT KEYS TO MAP *map-which-keys*
If you are going to map something, you will need to choose which key(s) to use
for the {lhs}. You will have to avoid keys that are used for Vim commands,
otherwise you would not be able to use those commands anymore. Here are a few
suggestions:
- Function keys <F2>, <F3>, etc.. Also the shifted function keys <S-F1>,
<S-F2>, etc. Note that <F1> is already used for the help command.
- Meta-keys (with the ALT key pressed). |:map-alt-keys|
- Use the '_' or ',' character and then any other character. The "_" and ","
commands do exist in Vim (see |_| and |,|), but you probably never use them.
- Use a key that is a synonym for another command. For example: CTRL-P and
CTRL-N. Use an extra character to allow more mappings.
See the file "index" for keys that are not used and thus can be mapped without
losing any builtin function. You can also use ":help {key}^D" to find out if
a key is used for some command. ({key} is the specific key you want to find
out about, ^D is CTRL-D).
Many Vim plugins use an initial <Leader> to start their key sequences; this is an (otherwise normally) unused key that is configurable by the user.
*<Leader>* *mapleader*
To define a mapping which uses the "mapleader" variable, the special string
"<Leader>" can be used. It is replaced with the string value of "mapleader".
If "mapleader" is not set or empty, a backslash is used instead. Example:
:map <Leader>A oanother line<Esc>
Works like:
:map \A oanother line<Esc>
But after:
:let mapleader = ","
It works like:
:map ,A oanother line<Esc>
Note that the value of "mapleader" is used at the moment the mapping is
defined. Changing "mapleader" after that has no effect for already defined
mappings.
Every single ASCII character, upper and lower case, is used for something in Vim. So you're going to wind up overwriting something--just pick something that you don't use. It may help to use a common idiom for your own extensions. I use a leading comma, for example:
map ,w :w!<CR>
map ,e :e #<CR>
imap ,, <ESC>
(The last is particularly useful for me, since I pretty much never need to write two consecutive commas in insert mode, and it's nice not to have to go all the way to the Esc key.)
Typically I use control + [letter] or alt + [letter] for most mappings and it's safe, but watch out for 'w' since that's needed for window commands. You might also be interested in arpeggio.vim which lets you create mappings to simultaneously pressed groups of keys - it will massively expand the possibilities for your mappings with no danger of over-mapping something. For example, you could map "dp" (pressed simultaneously) to execute "ddp" to delete and paste in one command.
Uhmm, no, don't. When creating your mappings try not to overwrite anything ... not so much because you don't use the command you're overmapping, but because some plugin which you have/or will have maybe using it.
And then you overmap it, and then you have to worry.
Personally, for commands such as you gave as an example, I like Ctrl+some key combinations. There are a lot of free ones in vim, and the letters on the left side near Ctrl make a nice pair then.
Btw, what are you trying to do with those mappings ... I understand the second one (delete word by word), but the first doesn't make sense to me. What is it supposed to do ? Transpose lines ?

Resources