forked from danielfrey/sublime-cucumber-step-finder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
cucumber_step_finder.py
154 lines (134 loc) · 5.33 KB
/
cucumber_step_finder.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
# -*- coding: utf-8 -*-
import sublime, sublime_plugin
import os
import re
import codecs
class CucumberBaseCommand(sublime_plugin.WindowCommand, object):
def __init__(self, window):
sublime_plugin.WindowCommand.__init__(self, window)
def settings_get(self, name):
# Get the plugin settings, default and user-defined.
plugin_settings = sublime.load_settings('CucumberStepFinder.sublime-settings')
# If this is a project, try to grab project-specific settings.
if sublime.active_window() and sublime.active_window().active_view():
project_settings = sublime.active_window().active_view().settings().get("CucumberStepFinder")
else:
project_settings = None
# Grab the setting, by name, from the project settings if it exists.
# Otherwise, default back to the plugin settings.
return (project_settings or {}).get(name, plugin_settings.get(name))
def find_step_in_file(self, root, f_name):
pattern = re.compile(r'((.*)(\/\^.*))\$\/')
step_file_path = os.path.join(root, f_name)
with codecs.open(step_file_path, encoding='utf-8') as f:
index = 0
for line in f:
match = re.match(pattern, line)
if match:
self.steps.append((match.group(), index, step_file_path))
index += 1
def find_all_steps(self, file_name=None):
features_path = self.settings_get('cucumber_features_path')
step_pattern = self.settings_get('cucumber_step_pattern')
self.steps = []
folders = self.window.folders()
if file_name == None:
for folder in folders:
if ( not os.path.exists(folder) ) : continue
for path in os.listdir(folder) + ['.']:
full_path = os.path.join(folder, path)
if path == features_path:
self.step_files = []
for root, dirs, files in os.walk(full_path, followlinks=True):
for f_name in files:
if re.match(step_pattern, f_name):
self.step_files.append((f_name, os.path.join(root, f_name)))
self.find_step_in_file(root, f_name)
else:
root = os.path.join(file_name)
self.find_step_in_file(root, file_name)
def determine_other_pane(self):
active_group = self.window.active_group()
num_groups = self.window.num_groups()
layout = self.window.get_layout()
cells = layout['cells']
cols = layout['cols']
if num_groups == 1:
# Only pane. Create a new one.
self.window.run_command('set_layout', {
"cols": [0.0, 0.5, 1.0],
"rows": [0.0, 1.0],
"cells": [[0, 0, 1, 1], [1, 0, 2, 1]]
})
return 1
elif active_group == num_groups - 1:
# Last pane in window. Use the previous one.
return active_group - 1
elif len(cols) > 2 and cells[active_group][2] == len(cols) - 1:
# Last pane in row. Use the previous one.
return active_group - 1
else:
# Otherwise, use the next one.
return active_group + 1
def step_found(self, index):
if index >= 0:
file_path = self.steps[index][2]
if self.settings_get('cucumber_new_pane') == True:
other_pane = self.determine_other_pane()
self.window.focus_group(other_pane)
match_view = self.window.open_file(file_path)
self.active_ref = (match_view, self.steps[index][1])
self.mark_step()
def mark_step(self):
view = self.window.active_view()
if view.is_loading():
sublime.set_timeout(self.mark_step, 50)
else:
view.run_command("goto_line", {"line": self.active_ref[1]+1} )
class MatchStepCommand(CucumberBaseCommand):
def __init__(self, window):
CucumberBaseCommand.__init__(self, window)
def run(self, file_name=None):
self.get_line()
def get_line(self):
view = self.window.active_view()
line_sel = view.line(view.sel()[0])
text_line = view.substr(line_sel).strip()
self.cut_words(text_line)
def cut_words(self, text):
words = self.settings_get('cucumber_code_keywords')
upcased = [up.capitalize() for up in words]
expression = "^{0}".format('|^'.join(upcased))
pattern = re.compile(expression)
short_text = re.sub(pattern, '', text).strip()
self.find_all_steps()
step_filter = re.compile(r'.*\/\^(.*)\$\/') # map all steps
steps_regex = [re.match(step_filter, x[0]).group(1) for x in self.steps]
for step in self.steps:
step_pattern = re.match(step_filter, step[0]).group(1)
step_regex = re.compile(step_pattern)
match = re.match(step_regex, short_text)
if match:
index = self.steps.index(step)
self.step_found(index)
else:
sublime.status_message('Can\'t find a match')
class CucumberStepFinderCommand(CucumberBaseCommand):
def __init__(self, window):
CucumberBaseCommand.__init__(self, window)
def run(self, file_name=None):
self.list_steps()
def list_steps(self):
self.find_all_steps()
steps_only = [x[0] for x in self.steps]
self.window.show_quick_panel(steps_only, self.step_found)
class CucumberStepFinderLocalCommand(CucumberBaseCommand):
def __init__(self, window):
CucumberBaseCommand.__init__(self, window)
def run(self, file_name=None):
self.list_steps()
def list_steps(self):
view = self.window.active_view()
self.find_all_steps(view.file_name())
steps_only = [x[0] for x in self.steps]
self.window.show_quick_panel(steps_only, self.step_found)