1

Let's say we wanted to produce the following text in a very "vim" way:

Row 1 {
  33.33%;
}
Row 2 {
  66.66%;
}
Row 3 {
  100%;
}

This isn't too complicated, but I think of it as a standin for something far more annoying, like having 12 rows (which might happen in CSS, for instance). I'm not interested in writing a whole plugin, because I think that is excessive.

Something I don't know too much about yet is using expressions () or making throw-away mappings. I bet these would lead to really clever, really nice ways.

It might be that the "right" way is to be clever with a macro involving :put =1.0/3 or something (this performs the division). But I'm not sure how to properly increment the numerator in this sort of expression.

It might be the "right" way to open a scratch buffer, write a quick throwaway function, and call it. But really, this is a very large hammer for a very small nail. There is some length of list where this would become more efficient than simply typing it, though.

There might be :ex magic or a really convenient commandline tool that I should pipe into vim, too.

There are so many options, and I'm not sure which are reasonable, and which are in the vim way.

To make this clear, I am not looking for the shortest way as in true code-golf, but instead a way that is extensible and comparable to making other formatted lists of numbers

2

I don't think there's going to be a non-horrible way to do this in Vim without a plugin.

If I absolutely had to do it within Vim, without just typing it out, I would call out to awk:

:r!awk 'BEGIN { for(i=1; i<4; i++) { print "Row " i " {"; print "\t" 100/3*i "\%;"; print "}"; } }'

1

This is really long and ugly, but here goes...

  1. Generating a list of initial numbers:

    i1<esc>qqyyp<C-a>q@q
    
    1
    2
    3
    

    If you need more, add n@@ to the end of this, where n is the amount of numbers more than three you need (i.e. if you want 20%, 40%, ..., 100%, then just append a 2@@).

  2. Convert these to percentages:

    V?1<cr>:s:.*:\=100.0*submatch(0)/3<cr>
    
    33.333333
    66.666667
    100.0
    

    I used : as the separator for s to avoid having to escape the / in the replacement section (which for some reason doesn't work), but you could use any other character as well.

    Also, this question taught me about \=! Found it via Google. submatch(0) is simply the entire matched text.

  3. Add the rest of the formatting:

    gv:s/^/Row {\r  /<cr>gvj:s/\([0-9]\)$/\1%\r}<cr>
    
    Row {
      33.333333%
    }
    Row {
      66.666667%
    }
    Row {
      100.0%
    }
    

    Sorry, this doesn't add the row numbers. I have to go now, further explanation will be added later.

The full thing:

i1<esc>qqyyp<C-a>q@qV?1<cr>:s:.*:\=100.0*submatch(0)/3<cr>gv:s/^/Row {\r  /<cr>gvj:s/\([0-9]\)$/\1%\r}<cr>

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.