Eran Medan
Eran Medan

Reputation: 45735

How to use regex to format a comma separated map structure

Using a text editor, without writing JavaScript functions (e.g. can't use this great answer: Replacing the nth instance of a regex match in Javascript)

How do I take something like this (a proprietary code structure I have no control over)

map(key1, value1, key2, value2, key3, value3, key4, value4 ...)

And convert it to this

map(
  key1, value1,
  key2, value2,
  key3, value3,
  key4, value4 
  ...
)

One option I found was using this regex to find every 2nd comma (([^,]*,){2})

Then replace with \1\n\t

But I would like to improve it:

1. It doen't handle the first and last lines very well

 map(key1, value1,
    key2, value2,
    key3, value3,
    key4, value4 ...)

2. Only works on a flat structure

e.g. I can't think of a way to transform this

map(key1, value1, key2, map(key3, value3, key4, value4 ...), key5, value5)

To this

map(
  key1,value1,
  key2,map(
    key3,value3,
    key4,value4 
  ),
  key5,value5    
)

Using regex, or is there a way?

Upvotes: 1

Views: 342

Answers (2)

Kent
Kent

Reputation: 195049

Eran, oh you finally tag the question with vim, nice! ^_^

vim can format it a bit, I wrote a small function:

Note that I used \r as linebreak, if it doesn't work for you, change into \n

function! ExpandMap()
    let s = line('.')
    exec 'silent s/(/(\r/g'
    let e = line('.')
    exec 'silent '.s.','.e.'s/),\=/\r&\r/g'
    let e = line('.')
    exec 'silent '.s.','.e.'s/,[^,]*\zs,\ze/,\r/g'
    let e = line('.')
    exec s.','.e.' normal =='
endfunction

You can put it in your .vimrc file, if you use that very often. Also you could just give it a try by typing :so %

You can create a map for that function call by:

`nnoremap <leader>r :call ExpandMap()<cr>`

in this way, if you want to reformat your map line, just move cursor to that line, and in Normal mode type <leader>r (default is \)

This function will change

map(k1, v1, k2,  map(k3, v3, k4, v4), k5, v5, k6, map(k7, v7,k8,v8,k9,v9),k10,v10,k11,v11)

into

map(
        k1, v1,
        k2,  map(
            k3, v3,
            k4, v4
            ),
        k5, v5,
        k6, map(
            k7, v7,
            k8,v8,
            k9,v9
            ),
        k10,v10,
        k11,v11
)

Here I show how it works:

  • I split the window into two, just show the function
  • I created a mapping after the function
  • I make two nested maps, also to make the line short, I just used k#, v#

enter image description here

Now, when are you gonna uninstall your notepad++? ^_^

Upvotes: 3

Blue Magister
Blue Magister

Reputation: 13363

A very basic implementation, replacing "Down" in the direction of text.

Find:

([^(,)]+,[^(,)]+)

Replace:

\n\t\1

Note that this does not work on ... (what is that?), and it does not do anything fancy with nesting depth. Keeping track of the nesting depth would require a parser with abilities beyond those of regex. Parsing a programming language is as hard as parsing HTML.

Upvotes: 1

Related Questions