Skip to content

Instantly share code, notes, and snippets.

Created June 3, 2012 13:26
Show Gist options
  • Star 46 You must be signed in to star a gist
  • Fork 25 You must be signed in to fork a gist
  • Save vitaLee/2863474 to your computer and use it in GitHub Desktop.
Save vitaLee/2863474 to your computer and use it in GitHub Desktop.
SublimeText command for compacting/expanding CSS rules
import sublime
import sublime_plugin
import re
class CompactExpandCssCommand(sublime_plugin.TextCommand):
def run(self, edit, action='compact'):
rule_starts = self.view.find_all('\{')
rule_ends = self.view.find_all('\}')
rules_regions = list()
regions_to_process = list()
selections = self.view.sel()
if len(selections) == 1 and selections[0].empty():
selections = [sublime.Region(0, self.view.size())]
for i in range(len(rule_starts)):
rule_region = sublime.Region(rule_starts[i].a, rule_ends[i].b)
for sel in selections:
if sel.intersects(rule_region):
self.process_rules_regions(regions_to_process, action, edit)
def process_rules_regions(self, regions, action, edit):
actions = {
'compact': self.compact_rules,
'expand': self.expand_rules,
'toggle': self.toggle_rules
actions[action](regions, edit)
def toggle_rules(self, regions, edit):
grouped_rules = list()
for r in regions:
action_key = 'expand' if self.rule_is_compact(r) else 'compact'
if not grouped_rules or not action_key in grouped_rules[-1]:
grouped_rules.append({action_key: []})
for group in grouped_rules:
for (action, rules) in group.items():
self.process_rules_regions(rules, action, edit)
def compact_rules(self, regions, edit):
view = self.view
for collapse_region in regions:
content = view.substr(collapse_region)
match = re.match(r"\{([^\}]*)\}", content)
rules =';')
rules = [r.strip() for r in rules]
rules = '; '.join(rules)
view.replace(edit, collapse_region, '{ ' + rules + '}')
def expand_rules(self, regions, edit):
view = self.view
for expand_region in regions:
content = view.substr(expand_region)
match = re.match(r"\{([^\}]*)\}", content)
rules =';')
rules = filter(lambda r: r.strip(), rules)
rules = ['\t' + r.strip() + ';\n' for r in rules]
rules = ''.join(rules)
view.replace(edit, expand_region, '{\n' + rules + '}')
def rule_is_compact(self, rule):
return re.match(r"^\{.*\}$", self.view.substr(rule))
// commands allow compacting/expanding of selected rules.
// multiple selections are supported
// commands are applied to rules which are covered by selection
// if there's a single empty selection then the command is applied to all rules within the document
// 1. save the file above under your Packages/User folder. for more info on where it's located on your platform look here -
// 2.1 add these to Packages/User/Default.sublime-commands to be able to execute through command list
// (if .sublime-commands doesn't exist there just create it by hand)
"caption": "CSS rules compact",
"command": "compact_expand_css",
"args": { "action": "compact" }
"caption": "CSS rules expand",
"command": "compact_expand_css",
"args": { "action": "expand" }
"caption": "CSS rules toggle",
"command": "compact_expand_css",
"args": { "action": "toggle" }
// or
// 2.2 map commands to keyboard shortcuts in Packages/User/Default(*your OS*).sublime-keymap to take the shortcut (if the file is not present, create by hand or go to Preferences -> Key Bindings - User).
// exmaple what the shortcut might look like
{ "keys": ["ctrl+super+]"], "command": "compact_expand_css", "args": { "action": "expand" } },
{ "keys": ["ctrl+super+["], "command": "compact_expand_css", "args": { "action": "compact" } },
Copy link

Thanks, @vitaLee, it was the square brackets that I had not known about. Now it works, very nice. (No restart necessary.)
I'd like to make a small suggestion: The compressed version has spaces before/behind the curly braces, which I like. But there's no space after the colons. Perhaps you might consider adding that.
Selecting all colons manually and adding a space does not work, because it adds spaces before "hover", "active", etc., too ...

Copy link

Well, done it myself:

rules = rules.replace(': ',':')
rules = rules.replace(':',': ')

after lines 62 and 77. Probably not the most elegant solution, but works for me!

Copy link

jhebb commented Sep 26, 2013

This is awesome, I've been searching all day for a solution for this - comes in super handy for updating older projects.

Did you ever update it for nested rules?

I added the suggestions from @lausianne and also these for my own preference to remove spaces before/after {} when collapsing:

rules = rules.rstrip(' ')

view.replace(edit, collapse_region, '{' + rules + '}')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment