import os
import sublime
import sublime_plugin
import re
PLUGIN_FILE = os.path.abspath(__file__)

def find_project_root(file_path):
    """Project Root is defined as the parent directory that contains a directory called 'coverage'"""
    if os.access(os.path.join(file_path, 'coverage'), os.R_OK):
        return file_path

    parent, current = os.path.split(file_path)
    if current:
        return find_project_root(parent)

def explode_path(path):
    first, second = os.path.split(path)
    if second:
        return explode_path(first) + [second]
    else:
        return [first]

class SublimeRubyCoverageListener(sublime_plugin.EventListener):
    """Event listener to highlight uncovered lines when a Ruby file is loaded."""

    def on_load(self, view):
        if 'source.ruby' not in view.scope_name(0):
            return

        view.run_command('show_ruby_coverage')

class ShowRubyCoverageCommand(sublime_plugin.TextCommand):
    """Highlight uncovered lines in the current file based on a previous coverage run."""

    def run(self, edit):
        view = self.view
        filename = view.file_name()
        if not filename:
            return

        project_root = find_project_root(filename)
        if not project_root:
            print 'Could not find coverage directory.'
            return

        relative_file_path = os.path.relpath(filename, project_root)

        coverage_filename = '-'.join(explode_path(relative_file_path))[1:].replace(".rb", "_rb.csv")
        coverage_filepath = os.path.join(project_root, 'coverage', 'sublime-ruby-coverage', coverage_filename)

        # Clean up
        view.erase_status('SublimeRubyCoverage')
        view.erase_regions('SublimeRubyCoverage')
        
        outlines = []

        if re.compile(r'.*?_spec\.rb$').match(filename) is None:
            try:
                with open(coverage_filepath) as coverage_file:
                    for current_line, line in enumerate(coverage_file):
                        if line.strip() != '1':
                            outlines.append(view.full_line(view.text_point(current_line, 0)))
            except IOError as e:
                outlines.append(sublime.Region(0,view.size()))
                view.set_status('SublimeRubyCoverage', 'UNCOVERED!')
                if view.window():
                    sublime.error_message("Oh dear. We can't seem to find the coverage file. We tried looking here: " + coverage_filepath + ", but then we gave up.")

        # update highlighted regions
        if outlines:
            view.add_regions('SublimeRubyCoverage', outlines, 'comment',
                sublime.DRAW_EMPTY | sublime.DRAW_OUTLINED)

@@ -1151,32 +1151,91 @@
         return%0A%0A
+        if self.file_exempt(filename):%0A            return%0A%0A
         project_
@@ -1810,77 +1810,8 @@
 %5B%5D%0A%0A
-        if re.compile(r'.*?_spec%5C.rb$').match(filename) is None:%0A    
     
@@ -1819,20 +1819,16 @@
    try:%0A
-    
         
@@ -1894,20 +1894,16 @@
         
-    
 for curr
@@ -1966,20 +1966,16 @@
         
-   
- 
 if line.
@@ -2014,36 +2014,25 @@
         
-    outlines.append(
+region = 
 view.ful
@@ -2075,47 +2075,543 @@
  0))
-)%0A            except IOError as e:%0A    
+%0A                        # join contiguous regions together%0A                        if len(outlines) %3E 0:%0A                            prev_region = outlines.pop()%0A                            if region.begin() == prev_region.end():%0A                                region = sublime.Region(prev_region.begin(), region.end())%0A                            else:%0A                                outlines.append(prev_region)%0A%0A                        outlines.append(region)%0A        except IOError as e:%0A            # highlight the entire view%0A
     
@@ -2665,20 +2665,16 @@
 ize()))%0A
-    
         
@@ -2742,20 +2742,16 @@
         
-    
 if view.
@@ -2756,28 +2756,24 @@
 w.window():%0A
-    
             
@@ -3114,8 +3114,408 @@
 TLINED)%0A
+%0A    def file_exempt(self, filename):%0A        normalized_filename = os.path.normpath(filename).replace('%5C%5C', '/')%0A        print normalized_filename%0A        for pattern in %5Br'/test/', r'/spec/', r'/features/', r'Gemfile$', r'Rakefile$', r'%5C.rake$'%5D:%0A            print pattern%0A            if re.compile(pattern).search(normalized_filename) is not None:%0A                return True%0A        return False%0A

handle file exemptions