2

In Python, I am trying to update my code from typed dict to dataclass. Language is just indicated as a reference, it is a pure Vim question.

I need to replace my_params["some_property"] with my_params.some_property

I have some difficulty replacing [".

How can I replace everything at once?

3

Since replacing everything at once is likely to accidentally get some wrong things, I would make sure to add the confirm flag, or be a bit cleverer: we’ll use the surround plugin and a macro to step through the file and make the changes.

  1. /\[": search for a pattern that should find all the things you need to change but may find extras. Press n until you’re on a match that needs changed.
  2. qqds[ds"i.<esc>q: record a macro that deletes square brackets, quotes, and inserts a dot.
  3. Press n/N to find places to edit and @q (the first time)/@@ (subsequent times) to make the change.
4
  • Note that ds comes from this plugin: github.com/tpope/vim-surround - it's not "vanilla" Vim. (AFAIK anyway :) )
    – Zoe
    Aug 19 at 8:37
  • @Zoe you’re correct: I usually am too lazy to add links to well-known plugins from mobile and forget to add them in. Edits welcome in all such cases.
    – D. Ben Knoble
    Aug 19 at 10:45
  • Oh, managed to miss the part where you said it was from a plugin. My bad!
    – Zoe
    Aug 19 at 10:52
  • 1
    @Zoe no worries :) thanks for making the link easy to add in!
    – D. Ben Knoble
    Aug 19 at 10:53
2

New version from @b-layer

:%s/\v\["([^"]+)"]/.\1/gc
  • %s targets the whole file
  • \v is the very magic modifier
  • \[" matches ["
  • ([^"]"+) represents the capture group for some_property, which [^"] ends at the next double quotes. + makes it at least one character.
  • \1 references the capture group in the replacement section
  • \g enables to replace for more than one occurrence per line and c asks for confirmation

Previous version:

I could perform the replacement executing the following command:

:%s/\v(\[")(.*)("\])/.\2/gc

where:

  • \v is the very magic modifier,
  • (\[")and ("\]) the capture groups 1 and 3 for the brackets and double quotes
  • (.*) the capture group 2, which is then referenced with \2 in the replacement section.
3
  • 2
    If you're not using them in the replacement you shouldn't need capture groups 1 and 3. Also, ] doesn't need to be escaped. Finally, .* is pretty greedy so it's usually safer to use a "not the next thing I want to match" pattern instead...in this case [^"]*. So :%s/\v\["([^"]*)"]/.\1/gc
    – B Layer
    Aug 17 at 9:36
  • 1
    (And it really should be a + rather than a * since my_params[""] isn't valid...but that's a small detail. :)
    – B Layer
    Aug 17 at 9:44
  • 1
    thanks for the very thorough review :) Aug 19 at 7:24
0

Given I sometime use single quotes and other times doubles quotes, here is another variation on B-Layer :substitute command that supports both, plus the reverse operation.

In order to remember the names, I've wrapped the two actions into commands.

command! -range=1
      \ ToAttribute <line1>,<line2>s/\v\[(["'])([^"']+)\1]/.\2/gc
command! -range=1 -nargs=? -complete=customlist,s:compl_to_dict
      \ ToDict      call s:to_dict(<f-args>)


" Internal support functions for :ToDict
function! s:to_dict(...) range abort
  let quote = get(a:, 1, "'")
  exe printf('%s,%ss/\v\.(\k+)/[%s\1%s]/gc', a:firstline, a:lastline, quote, quote)
endfunction

function! s:compl_to_dict(...) abort
  return ['"', "'"]
endfunction

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.