Vim - Sort Nested Blocks of SCSS

2

Note:

Can someone with 300 reputation please add the tag, "scss" to this question? I'd be very appreciative.


My code (scss):

.cinderblock {
    @include minwidth();
    background-image:url("images/cinderblock.jpg");
    background-position:top center;
    background-color:#b79966;
    height:528px;

    .wrapper {
        background-image:url("images/home-decorito.jpg");
        height:488px;
    }
    .big-yellow-button {
        width: auto;
        position:absolute;
        bottom:84px;
    }
}

What I need it to look like:

.cinderblock {
    @include minwidth();
    background-color:#b79966;
    background-image:url("images/cinderblock.jpg");
    background-position:top center;
    height:528px;

    .big-yellow-button {
        bottom:84px;
        position:absolute;
        width: auto;
    }
    .wrapper {
        background-image:url("images/home-decorito.jpg");
        height:488px;
    }
}

The solution must:

  • Alphabetically sort the
    • properties of the parent block
    • properties of the child blocks
    • child blocks
  • Preserve indentation
  • Bonus: Correct inconsistency in whitespace (e.g. spaces between property names and values)

gmeben

Posted 2013-04-10T17:27:36.260

Reputation: 73

If we leave the technical aspect of your question aside, this is not a very good idea. Selectors should be grouped by position on the page/in the site, cascading order, semantics… alphabetical sorting is probably worse than no order at all. – romainl – 2013-04-11T06:41:13.043

Actually, the best way to architect css is by specificity, especially when you're working on large sites like I do. Check it out: http://www.youtube.com/watch?v=R-BX4N8egEc

– gmeben – 2013-04-11T12:05:32.120

Hmm, that's what I meant with "cascading oder". Alphabetical order sucks, anyway. – romainl – 2013-04-11T12:08:06.760

Sorting properties and child selectors alphabetically is not a bad idea at all, as it cascades just fine and doesn't affect specificity. Please stay on topic. – gmeben – 2013-04-11T12:12:16.450

It affects readability and comprehension which should be the primary concern when talking about sorting text/code. width: 23px; and height: 46px; are conceptually related and thus should stay together, same thing for margin and padding or position, top, bottom, left and right. – romainl – 2013-04-11T13:02:55.393

If that's your cup of tea, then cool. Personally, I prefer alphabetical because if I'm looking for a specific property amongst a long list of declarations, I know where to look that much more quickly. When you work with large amounts of CSS/SCSS, it becomes a waste of time to manually organize properties (hence, my wish to automate) as they do not affect specificity. I'd much rather be using that time to manually organize selector order. – gmeben – 2013-04-11T13:28:47.470

OK, to each his/her own. I really heavily on search for that. – romainl – 2013-04-11T15:09:54.690

Answers

1

There's no easy/builtin way to do what you want. You'll obviously use the :sort command at one time or another but you'll need to come up with a couple of macros. Basically, the idea is to:

  1. put all your rules inline

    v%
    J
    (repeat)
    
  2. sort your selectors

    (select the inlined selectors)
    :'<,'>sort
    
  3. expand your blocks of rules and make it look good

    :s/\[{;\]/&\r
    =%
    
  4. sort each block

    (select the rules)
    :'<,'>sort
    

You can find some inspiration there.

romainl

Posted 2013-04-10T17:27:36.260

Reputation: 19 227

Cool, I'm gonna try this out soon – gmeben – 2013-04-11T12:14:12.880

I get punked on Step 2. I selected the inline selectors and punched in my sort, but they're still in the same order. Are you saying I need to sort the properties? – gmeben – 2013-04-11T13:40:15.100

at step 2 you should have only lines that start with selectors like .wrapper {...} or .big-yellow-button {...}. You should be able to sort all those lines by selecting them and do :sort without affecting what's between the curly brackets. – romainl – 2013-04-11T15:13:25.393

Ooh, you meant that I have to v%J each inline block individually. I see. Now I'm getting a "Pattern not found" error on Step 3. – gmeben – 2013-04-11T18:24:23.383

See the linked question for a more accurate pattern. – romainl – 2013-04-12T05:00:15.357

I can't make a pattern that works. This is where I need help. – gmeben – 2013-04-16T13:35:27.257

What pattern did you try? – romainl – 2013-04-16T13:37:17.653

Many, but they all failed. I'm not familiar enough with magic to know what to write. – gmeben – 2013-04-16T13:40:05.527

But you can't expect us to do all the work. Tell us what you did and we will pick up from that. – romainl – 2013-04-16T13:42:51.320

The patterns in the linked answer work. – romainl – 2013-04-16T13:47:02.043

Perhaps I'm not being clear. I can see those patterns do work. However, I need the magic to also preserve indentation and/or autoindent. – gmeben – 2013-04-16T14:12:57.240

Ah! That brand of magic will be hard to come up with. I'd suggest you simply do = to re-indent correctly. – romainl – 2013-04-16T14:24:50.500

It appears my newly-installed flavor of vim gets thrown off when attempting to = nested blocks in SCSS. – gmeben – 2013-04-16T17:42:17.860