forked from integrum/SublimeRubyCoverage
-
Notifications
You must be signed in to change notification settings - Fork 1
/
toggle_ruby_coverage.py
179 lines (152 loc) · 7.29 KB
/
toggle_ruby_coverage.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import os
import sublime
import sublime_plugin
from .common.theme_generator import ThemeGenerator
from .common.json_coverage_reader import JsonCoverageReader
class ToggleRubyCoverageCommand(sublime_plugin.TextCommand):
"""Show/hide coverage of current file based on a previous coverage run."""
def is_enabled(self):
return 'source.ruby' in self.view.scope_name(0)
def run(self, edit):
if 'source.ruby' not in self.view.scope_name(0):
return
settings = self.view.settings()
if settings.has('ruby_coverage.visible'):
self.hide_coverage()
settings.erase('ruby_coverage.visible')
else:
filename = self.get_filename()
coverage = self.get_coverage(filename)
self.show_coverage(filename, coverage)
settings.set('ruby_coverage.visible', True)
if self.is_auto_scroll_enabled():
self.scroll_to_uncovered()
def get_filename(self):
return self.view.file_name()
def get_coverage(self, filename):
view = self.view
r = JsonCoverageReader(filename)
coverage = r.get_file_coverage(filename) if r else None
return coverage
def show_coverage(self, filename, coverage):
view = self.view
self.augment_color_scheme()
if coverage is None:
self.show_no_coverage()
return
uncovered_regions = []
covered_regions = []
more_covered_regions = []
most_covered_regions = []
coverage_levels = sublime.load_settings("SimpleCov.sublime-settings").get("coverage_levels")
current_coverage_regions = None
self.reset_coverage_lines()
for line_number, line_coverage in list(enumerate(coverage['coverage'])):
if line_coverage is None:
self.add_coverage_line(line_number, None)
elif line_coverage >= coverage_levels['most_covered']:
self.add_coverage_line(line_number, most_covered_regions)
elif line_coverage >= coverage_levels['more_covered']:
self.add_coverage_line(line_number, more_covered_regions)
elif line_coverage >= coverage_levels['covered']:
self.add_coverage_line(line_number, covered_regions)
else:
self.add_coverage_line(line_number, uncovered_regions)
self.add_coverage_line(line_number + 1, None)
view.add_regions('ruby-coverage-uncovered-lines', uncovered_regions,
'coverage.uncovered')
view.add_regions('ruby-coverage-covered-lines', covered_regions,
'coverage.covered')
view.add_regions('ruby-coverage-more-covered-lines', more_covered_regions,
'coverage.covered.more')
view.add_regions('ruby-coverage-most-covered-lines', most_covered_regions,
'coverage.covered.most')
def reset_coverage_lines(self):
self.current_coverage_regions = None
self.current_region_start = None
def add_coverage_line(self, line_number, line_coverage_regions):
view = self.view
if self.current_coverage_regions is not line_coverage_regions:
if self.current_coverage_regions is not None:
current_region_end = view.full_line(view.text_point(line_number - 1, 0)).end()
self.current_coverage_regions.append(sublime.Region(self.current_region_start, current_region_end))
self.current_region_start = view.text_point(line_number, 0)
self.current_coverage_regions = line_coverage_regions
def show_no_coverage(self):
view = self.view
view.add_regions('ruby-coverage-uncovered-lines',
[sublime.Region(0, view.size())],
'coverage.uncovered')
if view.window():
sublime.status_message('No coverage data for this file.')
def hide_coverage(self):
view = self.view
self.restore_color_scheme()
view.erase_status('SimpleCov')
view.erase_regions('ruby-coverage-uncovered-lines')
view.erase_regions('ruby-coverage-covered-lines')
view.erase_regions('ruby-coverage-more-covered-lines')
view.erase_regions('ruby-coverage-most-covered-lines')
def is_auto_scroll_enabled(self):
settings = sublime.load_settings("SimpleCov.sublime-settings")
return settings.get("auto_scoll_to_uncovered", False)
def scroll_to_uncovered(self):
view = self.view
regions = view.sel()
if len(regions) > 1 or regions[0].size() > 0:
return
uncovered_lines = view.get_regions('ruby-coverage-uncovered-lines')
if uncovered_lines and len(uncovered_lines) > 0:
first_uncovered = uncovered_lines[0].a
view.sel().clear()
view.sel().add(sublime.Region(first_uncovered, first_uncovered))
view.show_at_center(first_uncovered)
def augment_color_scheme(self):
"""
Generate a new color scheme from the original with additional coverage-
related style rules added. Save this color scheme to disk and set it as
the target view's active color scheme.
(Hat tip to GitSavvy for this technique!)
"""
view = self.view
colors = sublime.load_settings("SimpleCov.sublime-settings").get("colors")
file_ext = self.get_filename_ext()
settings = view.settings()
original_color_scheme = settings.get("color_scheme")
settings.set("ruby_coverage.original_color_scheme", original_color_scheme)
themeGenerator = ThemeGenerator(original_color_scheme)
themeGenerator.add_scoped_style(
"SimpleCov Uncovered Line",
"coverage.uncovered",
background = colors["coverage"]["uncovered_background"],
foreground = colors["coverage"]["uncovered_foreground"]
)
themeGenerator.add_scoped_style(
"SimpleCov Covered Line",
"coverage.covered",
background = colors["coverage"]["covered_background"],
foreground = colors["coverage"]["covered_foreground"]
)
themeGenerator.add_scoped_style(
"SimpleCov More Covered Line",
"coverage.covered.more",
background = colors["coverage"]["covered_background_bold"],
foreground = colors["coverage"]["covered_foreground_bold"]
)
themeGenerator.add_scoped_style(
"SimpleCov Most Covered Line",
"coverage.covered.most",
background = colors["coverage"]["covered_background_extrabold"],
foreground = colors["coverage"]["covered_foreground_extrabold"]
)
themeGenerator.apply_new_theme("ruby-coverage-view." + file_ext, view)
def get_filename_ext(self):
filename = os.path.basename(self.get_filename())
period_delimited_segments = filename.split(".")
return '' if len(period_delimited_segments) < 2 else period_delimited_segments[-1]
def restore_color_scheme(self):
settings = self.view.settings()
original_color_scheme = settings.get("ruby_coverage.original_color_scheme")
if original_color_scheme:
settings.set("color_scheme", original_color_scheme)
settings.erase("ruby_coverage.original_color_scheme")