Raphael Pr
Raphael Pr

Reputation: 954

How to efficiently switch arguments in vim

I come upon one scenario when editing a file in vim and I still haven't found a way to do it quickly in vim way. When editing a call of a function, I offently put my arguments in a wrong order.

anyFunction(arg2, arg1)

When arriving on this situation, I have to find arg2 / delete it / append it before the ')' / deal with the ', ' / etc.

Isn't it a better way to this task quickly ? I am open to any idea (macro/ shortcut / plugin) even if I'd rather have a 'vim only' way of doing this

Upvotes: 4

Views: 5380

Answers (6)

anon
anon

Reputation:

Similar to what Peter Rincker suggested (Argumentative), sideways also does what you describe.

Upvotes: 1

Peter Rincker
Peter Rincker

Reputation: 45177

I actually made a plugin to deal with a exact 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.

Upvotes: 4

zzapper
zzapper

Reputation: 5041

put this mapping in your _vimrc.

 " gw : Swap word with next word 
 nmap <silent> gw :s/\(\%#\w\+\)\(\_W\+\)\(\w\+\)/\3\2\1/<cr><c-o><c-l>

then in normal mode with the cursor anywhere in arg1 type gw to swap parameters

 anyFunction(arg1, arg2)

Explanation:-

arg1 the separator (here a comma) and arg2 are put into regexp memories 1 2 3

the substitute reverses them to 3 2 1

Control-O return to last position

Control-L redraw the screen

Note that the separator is any non-alphanumeric character or string e,g whitespace

Upvotes: 3

Ingo Karkat
Ingo Karkat

Reputation: 172778

You need two things:

  1. A text object to quickly select an argument (as they aren't always that simple like in your example). argtextobj plugin (my improved fork here) does this.
  2. Though you can use delete + visual mode + paste + go back + paste, a plugin to swap text makes this much easier. My SwapText plugin or the already mentioned exchange plugin both do that job.

Upvotes: 4

Ben
Ben

Reputation: 8905

This is a perfect use for a regular expression search and replace.

You want to find "anyFunction(", then swap anything up to the ',' with anything from the ',' to the ')'. This is fairly straightforward, using [^,]* for "anything up to the ','" and [^)]* for "anything up to the ')'". Use \(...\) to capture each thing, and \1, \2 to refer to those things in the replacement:

:s#anyFunction(\s*\([^,]*\),\s*\([^)]*\)#anyFunction(\2, \1#g

Note how I use \s* to allow any whitespace between the "anyFunction(" and the first thing, and also between the ',' and the second thing.

If you want this to be able to span multiple lines, you can use \_s instead of \s, and capture the whitespace if you want to maintain the multi-line format:

:s#anyFunction(\(\_s*\)\([^,]*\),\(\_s*\)\([^)]*\)#anyFunction(\1\4,\3\2#g

There is also a multi-line variant of [...] collections, for example \_[^,] meaning "anything (even a new line) except for a ',' " which you could use in the pattern if your use case demands it.

For details, consult the help topics for: /\s, /\_s, /\1, /\(, and /[.

If you want a more general-purpose mapping to use at every location, you can use the cursor position in your regular expression, rather than keying off the function name. The cursor position in a regular expression is matched using \%# as demonstrated here: http://vim.wikia.com/wiki/Exchanging_adjacent_words

Upvotes: 1

Kent
Kent

Reputation: 195289

I would recommend a plugin: vim-exchange for that:

https://github.com/tommcdo/vim-exchange

Upvotes: 2

Related Questions