<commit_before>from collections import namedtuple
import re

import sublime
import sublime_plugin

from ..behave_command import BehaveCommand


class BstHighlightUndefinedSteps(sublime_plugin.TextCommand, BehaveCommand):

    '''
    Highlights undefined steps in a feature file.

    This command uses the 'steps.usage' format and parses its output to
    get the undefined steps.
    '''

    def run(self, edit, **kwargs):
        sublime.set_timeout_async(self.run_async, 0)

    def run_async(self):

        output = self.behave('--dry-run',
                             '--format',
                             'steps.usage',
                             '--no-summary',
                             '--no-snippets')
        offset = output.find('UNDEFINED STEPS')

        if offset != -1:
            output = output[offset:]

            # TODO: Improve this regex for better step name matching
            p = re.compile('^\s\s([\w+\s"]+)\s*#\s(.*):(\d+)$', re.MULTILINE)

            matched_set = re.findall(p, output)
            undefined_steps = []

            Step = namedtuple('Step', ['name', 'file', 'line', 'region'])

            for match in matched_set:
                name = match[0].strip()
                step = Step(name, match[1], match[2], self.view.find(name, 0))

                undefined_steps.append(step)

            self.view.add_regions('undefined_steps',
                                  [step.region for step in undefined_steps],
                                  'comment')<commit_msg>Fixed bug where regions don't clear when the last undefined step gets resolved<commit_after>from collections import namedtuple
import re

import sublime
import sublime_plugin

from ..behave_command import BehaveCommand


class BstHighlightUndefinedSteps(sublime_plugin.TextCommand, BehaveCommand):

    '''
    Highlights undefined steps in a feature file.

    This command uses the 'steps.usage' format and parses its output to
    get the undefined steps.
    '''

    def run(self, edit, **kwargs):
        sublime.set_timeout_async(self.run_async, 0)

    def run_async(self):

        output = self.behave('--dry-run',
                             '--format',
                             'steps.usage',
                             '--no-summary',
                             '--no-snippets')
        offset = output.find('UNDEFINED STEPS')

        region_name = 'bst.undefined_steps'

        if offset != -1:
            output = output[offset:]

            # TODO: Improve this regex for better step name matching
            p = re.compile('^\s\s([\w+\s"]+)\s*#\s(.*):(\d+)$', re.MULTILINE)

            matched_set = re.findall(p, output)
            undefined_steps = []

            Step = namedtuple('Step', ['name', 'file', 'line', 'region'])

            for match in matched_set:
                name = match[0].strip()
                step = Step(name, match[1], match[2], self.view.find(name, 0))

                undefined_steps.append(step)

            self.view.add_regions(region_name,
                                  [step.region for step in undefined_steps],
                                  'comment')
        else:
            # Clear regions if we can't find UNDEFINED STEPS in the output
            self.view.erase_regions(region_name)
{'fraction_non_alphanumeric': 0.11259079903147699, 'fraction_numerical': 0.0036319612590799033, 'mean_word_length': 1.7633779264214047, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3225666', 'n_tokens_mistral': 944, 'n_tokens_neox': 881, 'n_words': 232}