<commit_before>import os
import sublime
from sublime_plugin import TextCommand

from .common.json_coverage_reader import JsonCoverageReader
from .common.theme_generator import ThemeGenerator

PANEL_NAME = 'ruby-coverage-project'

class ShowProjectRubyCoverage(TextCommand):
    """Show coverage of all files in current file's project in a panel."""

    def run(self, edit):
        self.get_project_coverage()
        self.create_output_panel()
        self.display_project_coverage(edit)

    def get_project_coverage(self):
        filename = self.view.file_name()

        r = JsonCoverageReader(filename)
        self.coverage = r.get_project_coverage() if r else None

    def create_output_panel(self):
        self.panel = self.view.window().create_output_panel(PANEL_NAME)

    def display_project_coverage(self, edit):
        panel = self.panel
        panel.show(0)
        self.view.window().run_command("show_panel", {"panel": "output.{}".format(PANEL_NAME)})

        output, regions = self.format_project_coverage()

        panel.set_read_only(False)
        panel.erase(edit, sublime.Region(0, panel.size()))
        panel.insert(edit, 0, output)
        panel.set_read_only(True)

        self.augment_color_scheme()
        self.apply_regions(regions)

    def format_project_coverage(self):
        panel = self.panel
        files = self.coverage['files']

        output = ''

        viewport_width = int(panel.viewport_extent()[0] / panel.em_width())
        max_filename_length = len(max(files, key=lambda file: len(file['filename']))['filename'])
        coverage_length = len('100%')
        graph_width = viewport_width - max_filename_length - coverage_length - 7

        regions = [[], [], [], [], [], [], [], [], [], [], []]
        for file in files:
            graph_bar_width = int(file['covered_percent'] / 100.0 * graph_width)

            filename = file['filename'].ljust(max_filename_length)
            graph    = ''.ljust(graph_bar_width)
            coverage = '{:>5.1f}%'.format(file['covered_percent'])

            graph_region_start = len(output) + max_filename_length + len(coverage) + 2
            output += '{} {} {}\n'.format(filename, coverage, graph)

            decile = int(file['covered_percent'] / 10)
            regions[decile].append(sublime.Region(graph_region_start, graph_region_start + graph_bar_width))

        return output, regions

    def apply_regions(self, regions):
        view = self.panel

        for decile, decile_regions in list(enumerate(regions)):
            decile_percent = decile * 10
            view.add_regions('coverage-graph-{}'.format(decile_percent),
                             decile_regions,
                             'coverage.graph.{}'.format(decile_percent))

    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.panel

        settings = view.settings()
        self.restore_color_scheme()
        original_color_scheme = settings.get("color_scheme")
        settings.set("ruby_coverage.original_color_scheme", original_color_scheme)
        colors = sublime.load_settings("SublimeRubyCoverage.sublime-settings").get("colors")
        themeGenerator = ThemeGenerator(original_color_scheme)
        themeGenerator.add_scoped_style(
            "Coverage bar graph 0-9%",
            "coverage.graph.0",
            foreground = colors["graph"]["0"],<commit_msg>Add compact project coverage graph layout when viewport is narrow.<commit_after>import os
import sublime
from sublime_plugin import TextCommand

from .common.json_coverage_reader import JsonCoverageReader
from .common.theme_generator import ThemeGenerator

PANEL_NAME = 'ruby-coverage-project'

class ShowProjectRubyCoverage(TextCommand):
    """Show coverage of all files in current file's project in a panel."""

    def run(self, edit):
        self.get_project_coverage()
        self.create_output_panel()
        self.display_project_coverage(edit)

    def get_project_coverage(self):
        filename = self.view.file_name()

        r = JsonCoverageReader(filename)
        self.coverage = r.get_project_coverage() if r else None

    def create_output_panel(self):
        self.panel = self.view.window().create_output_panel(PANEL_NAME)

    def display_project_coverage(self, edit):
        panel = self.panel
        panel.show(0)
        self.view.window().run_command("show_panel", {"panel": "output.{}".format(PANEL_NAME)})

        output, regions = self.format_project_coverage()

        panel.set_read_only(False)
        panel.erase(edit, sublime.Region(0, panel.size()))
        panel.insert(edit, 0, output)
        panel.set_read_only(True)

        self.augment_color_scheme()
        self.apply_regions(regions)

    def format_project_coverage(self):
        panel = self.panel
        files = self.coverage['files']

        output = ''

        compact_layout = False
        viewport_width = int(panel.viewport_extent()[0] / panel.em_width()) - 3
        max_filename_length = len(max(files, key=lambda file: len(file['filename']))['filename'])
        coverage_length = len(' 99.9%')
        graph_width = viewport_width - max_filename_length - coverage_length - 1

        if graph_width < 11:
            # compact layout
            compact_layout = True
            max_filename_length = max(max_filename_length, viewport_width - coverage_length)
            graph_width = max_filename_length

        graph_regions = [[], [], [], [], [], [], [], [], [], [], []]
        for file in files:
            graph_bar_width = int(file['covered_percent'] / 100.0 * graph_width)

            filename = file['filename'].ljust(max_filename_length)
            decimal_places = 1 if file['covered_percent'] < 100 else 0
            coverage = ('{:>' + str(coverage_length - 1) + '.' + str(decimal_places) + 'f}%').format(file['covered_percent'])

            graph_region_start = len(output)
            graph_region_start += max_filename_length + len(coverage) + 1 if not compact_layout else 0
            output += '{}{}'.format(filename, coverage).ljust(viewport_width) + '\n'

            decile = int(file['covered_percent'] / 10)
            graph_regions[decile].append(sublime.Region(graph_region_start, graph_region_start + graph_bar_width))

        return output, graph_regions

    def apply_regions(self, regions):
        view = self.panel

        for decile, decile_regions in list(enumerate(regions)):
            decile_percent = decile * 10
            view.add_regions('coverage-graph-{}'.format(decile_percent),
                             decile_regions,
                             'coverage.graph.{}'.format(decile_percent))

    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.panel

        settings = view.settings()
        self.restore_color_scheme()
        original_color_scheme = settings.get("color_scheme")
        settings.set("ruby_coverage.original_color_scheme", original_color_scheme)
        colors = sublime.load_settings("SublimeRubyCoverage.sublime-settings").get("colors")
        themeGenerator = ThemeGenerator(original_color_scheme)
        themeGenerator.add_scoped_style(
            "Coverage bar graph 0-9%",
            "coverage.graph.0",
            foreground = colors["graph"]["0"],
{'fraction_non_alphanumeric': 0.11061266341963599, 'fraction_numerical': 0.006921302230197385, 'mean_word_length': 2.797080291970803, 'pattern_counts': {'":': 2, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5911922', 'n_tokens_mistral': 2313, 'n_tokens_neox': 2187, 'n_words': 455}