Swap items in comma separated list - vim

Frequently, e.g. when I write Latex code, I come across the task to rearrange items of a list that are separated by commas. This is quickly done if both items are not at the at the beginning or the end of the list. But if they are at the margins, one has to take extra care of the separating comma.
As an example consider
\cite{GirR84, Tar00, Tem77}.
Is there a smart way in vim to put, e.g., the last item to the front or to the middle position?

I actually made a plugin to deal with a similar situation called argumentative.vim. (Sorry for the plug.)
Argumentative.vim provides the following mappings:
[, and ], motions which will go to the previous or next argument
<, and >, to shift an argument left or right
i, and a, argument text objects. e.g. da,, ci, or yi,
So with this plugin you move to the argument in question and then do a <, or >, as many times as needed. It can also take a count e.g. 2>,.
If you have Tim Pope's excellent repeat.vim plugin installed <, and >, become repeatable with the . command.

I have the following mappings in .vimrc, I think I have them from this tip on wikia:
nnoremap <silent> gl "_yiw:s/\(\%#\w\+\)\(\_W\+\)\(\w\+\)/\3\2\1/<CR><c-o>/\w\+\_W\+<CR><c-l>
nnoremap <silent> gh "_yiw?\w\+\_W\+\%#<CR>:s/\(\%#\w\+\)\(\_W\+\)\(\w\+\)/\3\2\1/<CR><c-o><c-l>
gh will swap word under the cursor to the left and gl to the right.

Another interesting way of swapping arbitrary things from the Vim Tips Wiki:
:vnoremap <C-X> <Esc>`.``gvP``P

You could try the vim plugin vim-swap, quite powerful and useful!

Related

Is it possible to scroll multiple lines of auto-completion with Control-p and Control-n in vim?

The Vim documentation states that one can use Control-p to go to the previous match. However, if I want to go up 10 lines in the autocompletion menu, I need to type Control-p ten times.
Is it possible to specify a count so I can scroll up (or down) 10 rows without the extra keystrokes?
All printable characters are inserted "as-is" so 10<whatever> is impossible out of the box. You can use <PageUp> and <PageDown> but they behave exactly how you would expect so, if the goal is to select a match somewhere in the middle of the visible menu, they won't help.
One hacky solution could be to map n non-printable keys that do <Down> n times but that doesn't sound practical at all.
Or you could intercept numbers and do <Down>/<Up> for as many times as specified but handling multiple digits seems like a hassle and how would you handle actually inserting digits?
This will do pretty much what you ask for:
function! CleverTab(cnt)
return repeat("\<C-P>", a:cnt)
endfunction
inoremap 2<C-P> <C-R>=CleverTab(2)<CR>
inoremap 3<C-P> <C-R>=CleverTab(3)<CR>
inoremap 4<C-P> <C-R>=CleverTab(4)<CR>
"....

Insert character without entering insert mode?

Sometimes I want to insert a # to comment out a line and test it quickly. Currently I do:
i#ESC:w
Is there something shorter I can do?
Although I agree with others that there are better ways to comment and uncomment code, it seems that people have gotten distracted and forgotten to actually answer the question.
This is my approach to inserting a single character:
:noremap <key> i <Esc>r
I tend to find that I need to replace, remove, or add single characters very often if I'm correcting typos, so (resp.) r, x, and whatever is chosen for <key> in the above become very handy.
Note that . is also particularly handy for this sort of task. It repeats the previous action.
Personally though, I only map this function to a valuable key when I'm doing a task where I use it frequently enough to justify occupying a prime spot on the keyboard (such as correcting typos), because really, it only saves one keystroke per use and that's only when <key> is not a combination, which of course limits availability.
I map a couple of things to my <leader> key (\ by default):
" # comment the current line
nnoremap <leader>d I#<ESC>
" block comment in visual mode
vnoremap <leader>c <ESC>'<O/*<ESC>'>o*/<ESC>V'<k
If you want to add a # to the start of a group of lines, then do this:
<ctl-v>
j (as many times as necessary
I#
<esc>
You could use a recording. From normal mode, type:
qlml0i#<press escape>`lq
Then to comment out a line, just press #l
Mapping in vim is so easy that I might do something like
:nmap CC I#<Esc>:w<CR>
on the fly. If I get used to it, then I will add it to my vimrc file.
:help key-mapping
:help usr_40.txt
Actually there is a plugin you might wanna take a look at:
http://www.vim.org/scripts/script.php?script_id=1218
It is specifically designed for that purpose.
I'm particularly fond of the tComment plugin. gcc to comment a line, repeat to uncomment, multiple lines, motions, etc.

How can I delete empty lines in motion in 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.

Advanced Usage of Ranges with Vim Keymappings

I have a mapping in my vimrc that downwardly comments out regions of c code:
nmap comc :normal! I//<ESC>
Since the 'normal' ex command implicitly converts input such as "Ncomc" to ".,.+N-1 comc", I can range comments downwardly without many keystrokes and without leaving normal mode. This is, however, a very limited subset of what vim ranges can do. If I'm willing to be verbose, I can achieve upward ranging comments like so:
.,.-5 normal comc
While editing text, I would much prefer to type something like "-6comc" or make a mapping of "Comc" that uses upward ranges. I'm haven't been able to do so successfully.
Similarly, range operations support commenting until a search pattern is reached, e.g :
.,/int main/ comc
I would, however, like to do so without all that typing.
The behavior you requested is normally done with :h map-operator mapping. With this commenting 3 lines down will turn into comc2j though, but 3 lines up is now just as easy: comc2k.
You can also use visual mode without changing your mapping at all: V2kcomc. You will have to add xnoremap with the identical lhs and rhs because nnoremap works only for normal mode. (And do not use nmap.)
Third option is mapping - to something that moves {count} lines up and puts count back:
nnoremap <expr> - (v:count ? ":\<C-u>\n" . (v:count-1) . 'k' . v:count : '')
. This assumes you are writing 6-comc, not -6comc.
// By the way, I would suggest The NERD Commenter if it comes to the plugin.
While it's commendable to go as far as possible without any plugins, sometimes they're just the best option. What will you do when you start working in a language that has comments with # or (*...*)? Add new mappings for these comment characters?
I recommend commentary.vim which does filetype-aware commenting.
The default commenting operator in commentary.vim is gc. You can combine it with motions, and use it in Visual mode too.
Your use cases:
Comment downwards N lines (say, 3): :.,.+3normal gcc, or gc3j or 4gcc.
Comment upwards 5 lines: :.,.-5normal gcc, or simply gc5k.
Comment until int main: :.,/int main/-1normal gcc, or simply gc/int main followed by Enter.

Vim: move around quickly inside of long line

I have word-wrap enabled and tend to have quite long lines.
But moving around inside a line that's actually 4 lines high with "w" is cumbersome. I keep using / to jump to the word I'm looking for, but that seems overdoing it a bit.
Any hints on how to move more quickly inside of a line?
Thanks,
MrB
You can use $, 0, and ^ to move to line endpoints and then use w and b. Also, adding a numeric argument to w and b can accelerate the process, so using 6w instead of just w can put you about to where ou need to be.
Using f and t to move to individual characters will help also. (I use this typically with punctuation. If, for example, I have four sentences on one long line 2f. will go to the end of the second sentence)
Using the ( and ) keys are an alternative way to navigate entire sentences.
Splitting out long lines into multiple lines (manually, or with set tw=72 [or 80]) can make editing them simpler. You can always join them later with J.
Something I just discovered, you can move up and down one displayed line by using gj and gk. That way, you can treat your one wrapped line as multiple lines.
If you comment on the type of data you're editing, it might make it easier for us to make suggestions.
I think you can benefit from gk and gj instead of just k and j.
Also look at 'virtualedit' for some options that allow you to cursor through 'void' areas without flicking the cursor to the next best physical character.
You might want to (temporarily)
nnoremap <buffer> k gk
nnoremap <buffer> j gj
Leave out the <buffer> part to apply this globally.
You can use ( and ) to navigate by sentence; it just looks for ., but that can be immensely helpful, especially if you don't like the sentence and want to change it: (c) will jump to the beginning of the current sentence, then change the entire sentence.
You can also use w and e, with count modifiers, to move words. 3w will move three words at a time.
You can also use f and F to search forward and backwards for a specific character. This is much more useful if you're looking for the word quite or syzygy than the. :)
My preferred strategy while jumping around long lines is to use f F and t T to zero in on the character. What makes this family of motions supercharged is that you can utilize the ; and , motions, so you don't have to count the position of character relative to cursor, but just step through them (extremely useful with
' " . etc)
Let's say we have a line:
reallyLongObjectName.longMethod().prettyPrettyLongMethod().burp();
If we need to jump to, say, the third dot from the beginning of the line, we can use either 3f. or f.;; visiting two dots and landing on third.
While the ; , style can use more keystrokes, I found it more agile and fun overall.
If you choose to go the route of remapping these:
nnoremap k gk
nnoremap j gj
here are a couple others along the same lines:
nnoremap 0 g0
nnoremap $ g$
nnoremap ^ g^
I recently started using a plugin that I find really nice to move very quickly inside a line (or the whole file).
The plugin's name is PreciseJump and you can find it here.
When you use this plugin it defines to mappings _f and _F.
If you type _f followed by x it will highlight all x characters and will replace temporarily with other characters that you can press to jump to that location. Check the script page for an illustration.
You can also move around with W B that will skip to the next space :)
G moves to the end of the document
Please notice that using "g" followed by Up or Down arrows indeed works fine, but if you have long lines and move quickly you may enter "gg" by mistake and end-up at the top of the text...! (Undo will not bring you back, and AFAIK there is not one-key-pressed way to go back to where you were.)
It happened to me too many times.
What I did was, and I suggest you, to modify (or create) your "~/.vimrc" and add these two lines:
map <C-Up> g<Up>
map <C-Down> g<Down>
This will map you control-up and control-down to the movements commands. Will make mistyping "gg" impossible and is perfectly coherent with control-right and control-left to move around long lines.
If you add these other two lines, you can use the same command in insert mode (!)
imap <C-Up> <C-[> g<Up> i
imap <C-Down> <C-[> g<Down> i
(VIM is great !)
Greg Ruo

Resources