1

What is the most efficient way to change Ruby's hashrocket notation into the name: 'value' notation in vim?

Some examples:

{ 
  :id => site.id,
  :primary_domain => site.name,
  :wp_admin_url => site.wp_admin_url
}
{ 
  id: site.id,
  primary_domain: site.name,
  wp_admin_url: site.wp_admin_url
}


{ :id => site.id, :primary_domain => site.name }
{ id: site.id, primary_domain: site.name }


Site.find_by(:access_token => params[:access_token], :primary_domain => params[:primary_domain])
Site.find_by(access_token: params[:access_token], primary_domain:params[:primary_domain])

Do you have a macro for this? Some more efficient sequence then mine? Use search-replace? The most efficient I can come up with, is quite manual and requires some repetiotion:

ft:xpldf> go to the first :, delete it and paste it after the word, then move one character forward and delete the => part. This needs to be repeated for each :name => value part in a Hash. And cannot be simply ran N times, because there might very well be some :symbols that need to remain, like in the last example.

How do you quickly change from the Hashrocket notation?

Community
  • 1
  • 1
berkes
  • 26,996
  • 27
  • 115
  • 206
  • 1
    Tricky. I prepared a macro recording for you until I noticed that third example of yours. To handle such cases one needs a parser, which knows what syntactic element it is working on. I'm not able to create such with a simple recording. – mvw Mar 21 '14 at 11:30

3 Answers3

6

This substitution seems to do the trick on all three samples:

:%s/:\(\w\+\)\s*=>\s*/\1: /g

You can create a simple custom command out of it:

command! Notation %s/:\(\w\+\)\s*=>\s*/\1: /g

or a slightly smarter one:

command! -range=% Notation silent execute <line1>.','.<line2>.'s/:\(\w\+\)\s*=>\s*/\1: /g'
romainl
  • 186,200
  • 21
  • 280
  • 313
  • 1
    This is pretty much on the right track but it doesn't add single quotes to the value. `%s/:\(\w\+\) *=> *\([a-zA-Z0-9._-]\+\)/\1: '\2'/g` is along the right lines, but might need further tweaking. – slim Mar 21 '14 at 11:10
  • Stupid me, I forgot the quotes. – romainl Mar 21 '14 at 11:13
  • Thanks, I also learned about `help command` today. That was mostly the missing part. – berkes Mar 21 '14 at 11:16
  • Well quotes are not needed in the OP's samples but yeah, it needs a bit of tinkering to make it really generic. – romainl Mar 21 '14 at 11:21
1

FYI: This regexp actually broke for me.

I had some code like: Module::Class.where(:symbol => ...

So the regexp tried to match from the :: onward.

Instead, I used:

:1,$s/:\([^\:\s]\+\)\s\+=>/\1:/gc
Enamul Hassan
  • 5,266
  • 23
  • 39
  • 56
0

In the spirit of iterative improvement, the following should also preserve whitespace between the key-value pairs (e.g. when rockets are tabbed over to align them, assuming space between the rocket and value doesn't need to be preserved):

:%s/:(\w+)(\s*)=>\s*/\1:\2/g

Should work with all of the following examples:

:key => value

Module::Class.where(:symbol => value)

{ 
  :id => site.id,
  :primary_domain => site.name
}

Site.find_by(:access_token => params[:access_token], :primary_domain => params[:primary_domain])

:symbol_one => some_method(:symbol_two).other_method(:symbol_3 => third_method(:symbol_4).attribute)

:to   => :processing_payment,
:from => [:awaiting_contact, :awaiting_payment]

Luke Abel
  • 243
  • 2
  • 9