Example bad:
#main {
padding:0;
margin: 10px auto;
}
Example good:
#main {padding:0;margin:10px auto;}
I have a ton of CSS rules that are taking up too many lines. And I cannot figure out the :%s/
commands to use.
Example bad:
#main {
padding:0;
margin: 10px auto;
}
Example good:
#main {padding:0;margin:10px auto;}
I have a ton of CSS rules that are taking up too many lines. And I cannot figure out the :%s/
commands to use.
Try something like this:
:%s/{\n/{/g :%s/;\n/;/g :%s/{\s+/{/g :%s/;\s+/;/g
This removes the newlines after opening braces and semicolons ('{' and ';') and then removes the extra whitespace between the concatenated lines.
If you are at the beginning or end of the rule, V%J
will join it into a single line:
V
to enter visual mode%
to match the other brace, selecting the whole ruleJ
to join the linesGo to the first line of the file, and use the command gqG
to run the whole file through the formatter. Assuming runs of nonempty lines should be collapsed in the whole file.
Here's a one-liner:
:%s/{\_.\{-}}/\=substitute(submatch(0), '\n', '', 'g')/
\_.
matches any character, including a newline, and \{-}
is the non-greedy version of *
, so {\_.\{-}}
matches everything between a matching pair of curly braces, inclusive.
The \=
allows you to substitute the result of a vim expression, which we here use to strip out all the newlines '\n'
from the matched text (in submatch(0)
) using the substitute()
function.
The inverse (converting the one-line version to multi-line) can also be done as a one liner:
:%s/{\_.\{-}}/\=substitute(submatch(0), '[{;]', '\0\r', 'g')/
If you want to change the file, go for rampion's solution.
If you don't want (or can't) change the file, you can play with a custom folding as it permits to choose what and how to display the folded text. For instance:
" {rtp}/fold/css-fold.vim
" [-- local settings --] {{{1
setlocal foldexpr=CssFold(v:lnum)
setlocal foldtext=CssFoldText()
let b:width1 = 20
let b:width2 = 15
nnoremap <buffer> + :let b:width2+=1<cr><c-l>
nnoremap <buffer> - :let b:width2-=1<cr><c-l>
" [-- global definitions --] {{{1
if exists('*CssFold')
setlocal foldmethod=expr
" finish
endif
function! CssFold(lnum)
let cline = getline(a:lnum)
if cline =~ '{\s*$'
return 'a1'
elseif cline =~ '}\s*$'
return 's1'
else
return '='
endif
endfunction
function! s:Complete(txt, width)
let length = strlen(a:txt)
if length > a:width
return a:txt
endif
return a:txt . repeat(' ', a:width - length)
endfunction
function! CssFoldText()
let lnum = v:foldstart
let txt = s:Complete(getline(lnum), b:width1)
let lnum += 1
while lnum < v:foldend
let add = s:Complete(substitute(getline(lnum), '^\s*\(\S\+\)\s*:\s*\(.\{-}\)\s*;\s*$', '\1: \2;', ''), b:width2)
if add !~ '^\s*$'
let txt .= ' ' . add
endif
let lnum += 1
endwhile
return txt. '}'
endfunction
I leave the sorting of the fields as exercise. Hint: get all the lines between v:foldstart+1 and v:voldend in a List, sort the list, build the string, and that's all.
I won't answer the question directly, but instead I suggest you to reconsider your needs. I think that your "bad" example is in fact the better one. It is more readable, easier to reason about and modify. Good indentation is very important not only when it comes to programming languages, but also in CSS and HTML.
You mention that CSS rules are "taking up too many lines". If you are worried about file size you should consider using CSS/JS minifier like YUI Compressor instead of making the code less readable.