howzit 2.1.16 → 2.1.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +74 -0
- data/bin/howzit +67 -67
- data/howzit.gemspec +3 -1
- data/lib/howzit/buildnote.rb +224 -38
- data/lib/howzit/prompt.rb +19 -7
- data/lib/howzit/run_report.rb +51 -0
- data/lib/howzit/stringutils.rb +3 -1
- data/lib/howzit/task.rb +21 -2
- data/lib/howzit/topic.rb +24 -1
- data/lib/howzit/util.rb +5 -1
- data/lib/howzit/version.rb +1 -1
- data/lib/howzit.rb +11 -2
- data/spec/buildnote_spec.rb +59 -3
- data/spec/cli_spec.rb +1 -1
- data/spec/run_report_spec.rb +35 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/topic_spec.rb +5 -2
- metadata +6 -18
- data/.editorconfig +0 -9
- data/.github/FUNDING.yml +0 -2
- data/.gitignore +0 -45
- data/.howzit.taskpaper.bak +0 -27
- data/.irbrc +0 -6
- data/.rspec +0 -2
- data/.rubocop.yml +0 -48
- data/.travis.yml +0 -17
- data/.yardopts +0 -6
- data/lib/.rubocop.yml +0 -1
- data/spec/.rubocop.yml +0 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a6cac91a8b188ff256fa863ad94e134e820ed2aa2eb766a10fea38ee745de750
|
|
4
|
+
data.tar.gz: 90799282be7a348b595df19a5c09850db8ac4d653bd81063d49f1830e6cb0761
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6b98ee5eb923878803f0268080ad1d56f4f9aed7279e6dcb245f13659e3a947348212741b3409861aacff145bc5abb19af7dd9810a854626e6b5067fc33ad954
|
|
7
|
+
data.tar.gz: 9be180170d36f0f415e3f0977b5b951368f7498fe630cd4f900626bf852c5678b860cea8ac63472dec0c03c41531cf70eb58a5002298a5ed9f5661204aa6d7cb
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,77 @@
|
|
|
1
|
+
### 2.1.21
|
|
2
|
+
|
|
3
|
+
2025-12-13 05:03
|
|
4
|
+
|
|
5
|
+
#### NEW
|
|
6
|
+
|
|
7
|
+
- Prefer exact whole-word topic matches over fuzzy matches
|
|
8
|
+
- Display run summary after executing tasks
|
|
9
|
+
|
|
10
|
+
#### IMPROVED
|
|
11
|
+
|
|
12
|
+
- Topic matching now handles colons/commas in topic titles
|
|
13
|
+
- Smart splitting of multiple topics preserves separators in titles
|
|
14
|
+
- Single match from choose now auto-selects without menu
|
|
15
|
+
- Combined output from multiple topics paginated together
|
|
16
|
+
- Menu prompt shows the search term being matched
|
|
17
|
+
|
|
18
|
+
#### FIXED
|
|
19
|
+
|
|
20
|
+
- String uncolor deleting characters
|
|
21
|
+
- Broken pipe error when quitting pager early
|
|
22
|
+
|
|
23
|
+
### 2.1.20
|
|
24
|
+
|
|
25
|
+
2025-12-13 05:01
|
|
26
|
+
|
|
27
|
+
#### NEW
|
|
28
|
+
|
|
29
|
+
- Prefer exact whole-word topic matches over fuzzy matches
|
|
30
|
+
- Display run summary after executing tasks
|
|
31
|
+
|
|
32
|
+
#### IMPROVED
|
|
33
|
+
|
|
34
|
+
- Topic matching now handles colons/commas in topic titles
|
|
35
|
+
- Smart splitting of multiple topics preserves separators in titles
|
|
36
|
+
- Single match from choose now auto-selects without menu
|
|
37
|
+
- Combined output from multiple topics paginated together
|
|
38
|
+
- Menu prompt shows the search term being matched
|
|
39
|
+
|
|
40
|
+
#### FIXED
|
|
41
|
+
|
|
42
|
+
- String uncolor deleting characters
|
|
43
|
+
- Broken pipe error when quitting pager early
|
|
44
|
+
|
|
45
|
+
### 2.1.19
|
|
46
|
+
|
|
47
|
+
2025-12-13 05:01
|
|
48
|
+
|
|
49
|
+
#### NEW
|
|
50
|
+
|
|
51
|
+
- Prefer exact whole-word topic matches over fuzzy matches
|
|
52
|
+
- Display run summary after executing tasks
|
|
53
|
+
|
|
54
|
+
#### IMPROVED
|
|
55
|
+
|
|
56
|
+
- Topic matching now handles colons/commas in topic titles
|
|
57
|
+
- Smart splitting of multiple topics preserves separators in titles
|
|
58
|
+
- Single match from choose now auto-selects without menu
|
|
59
|
+
- Combined output from multiple topics paginated together
|
|
60
|
+
- Menu prompt shows the search term being matched
|
|
61
|
+
|
|
62
|
+
#### FIXED
|
|
63
|
+
|
|
64
|
+
- String uncolor deleting characters
|
|
65
|
+
- Broken pipe error when quitting pager early
|
|
66
|
+
|
|
67
|
+
### 2.1.18
|
|
68
|
+
|
|
69
|
+
2025-01-01 09:53
|
|
70
|
+
|
|
71
|
+
#### IMPROVED
|
|
72
|
+
|
|
73
|
+
- Include named arguments when listing runnable topics
|
|
74
|
+
|
|
1
75
|
### 2.1.16
|
|
2
76
|
|
|
3
77
|
2024-08-13 10:59
|
data/bin/howzit
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env ruby
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
|
-
$LOAD_PATH.unshift File.join(__dir__,
|
|
5
|
-
require
|
|
4
|
+
$LOAD_PATH.unshift File.join(__dir__, "..", "lib")
|
|
5
|
+
require "howzit"
|
|
6
6
|
|
|
7
7
|
Howzit::Color.coloring = $stdout.isatty
|
|
8
8
|
|
|
@@ -13,127 +13,127 @@ Howzit.named_arguments = {}
|
|
|
13
13
|
|
|
14
14
|
OptionParser.new do |opts|
|
|
15
15
|
opts.banner = "Usage: #{File.basename(__FILE__)} [OPTIONS] [TOPIC]"
|
|
16
|
-
opts.separator
|
|
17
|
-
opts.separator
|
|
18
|
-
Include a topic name to see just that topic, or no argument to display all.
|
|
19
|
-
opts.separator
|
|
20
|
-
opts.separator
|
|
16
|
+
opts.separator ""
|
|
17
|
+
opts.separator "Show build notes for the current project (buildnotes.md).
|
|
18
|
+
Include a topic name to see just that topic, or no argument to display all."
|
|
19
|
+
opts.separator ""
|
|
20
|
+
opts.separator "Options:"
|
|
21
21
|
|
|
22
22
|
opts.separator " Behavior:\n\n" #=================================================================== BEHAVIOR
|
|
23
23
|
|
|
24
|
-
opts.on(
|
|
24
|
+
opts.on("--ask", "Request confirmation for all tasks when running a topic") { Howzit.options[:ask] = true }
|
|
25
25
|
|
|
26
|
-
opts.on(
|
|
27
|
-
raise
|
|
26
|
+
opts.on("--default", "Answer all prompts with default response") do
|
|
27
|
+
raise "--default cannot be used with --yes or --no" if Howzit.options[:yes] || Howzit.options[:no]
|
|
28
28
|
|
|
29
29
|
Howzit.options[:default] = true
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
opts.on(
|
|
32
|
+
opts.on("-f", "--force", "Continue executing after an error") { Howzit.options[:force] = true }
|
|
33
33
|
|
|
34
|
-
opts.on(
|
|
35
|
-
|
|
34
|
+
opts.on("-m", "--matching TYPE", MATCHING_OPTIONS,
|
|
35
|
+
"Topics matching type", "(#{MATCHING_OPTIONS.join(", ").sub(/#{Howzit.options[:matching]}/, "*#{Howzit.options[:matching]}")})") do |c|
|
|
36
36
|
Howzit.options[:matching] = c
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
-
opts.on(
|
|
40
|
-
|
|
39
|
+
opts.on("--multiple TYPE", MULTIPLE_OPTIONS,
|
|
40
|
+
"Multiple result handling", "(#{MULTIPLE_OPTIONS.join(", ").sub(/#{Howzit.options[:multiple_matches]}/, "*#{Howzit.options[:multiple_matches]}")}, default choose)") do |c|
|
|
41
41
|
Howzit.options[:multiple_matches] = c.to_sym
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
opts.on(
|
|
44
|
+
opts.on("-u", "--[no-]upstream", "Traverse up parent directories for additional build notes") do |p|
|
|
45
45
|
Howzit.options[:include_upstream] = p
|
|
46
46
|
end
|
|
47
47
|
|
|
48
|
-
opts.on(
|
|
49
|
-
raise
|
|
48
|
+
opts.on("-y", "--yes", "Answer yes to all prompts") do
|
|
49
|
+
raise "--default cannot be used with --yes" if Howzit.options[:default]
|
|
50
50
|
|
|
51
51
|
Howzit.options[:yes] = true
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
opts.on(
|
|
55
|
-
raise
|
|
54
|
+
opts.on("-n", "--no", "Answer no to all prompts") do
|
|
55
|
+
raise "--default cannot be used with --no" if Howzit.options[:default]
|
|
56
56
|
|
|
57
57
|
Howzit.options[:no] = true
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
opts.separator "\n Listing:\n\n" #=================================================================== LISTING
|
|
61
61
|
|
|
62
|
-
opts.on(
|
|
62
|
+
opts.on("-L", "--list-completions", "List topics (completion-compatible)") do
|
|
63
63
|
Howzit.options[:list_topics] = true
|
|
64
64
|
Howzit.options[:list_topic_titles] = true
|
|
65
65
|
end
|
|
66
66
|
|
|
67
|
-
opts.on(
|
|
67
|
+
opts.on("-l", "--list", "List available topics") do
|
|
68
68
|
Howzit.options[:list_topics] = true
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
opts.on(
|
|
71
|
+
opts.on("-R", "--list-runnable [PATTERN]", "List topics containing @ directives (verbose)") do |pat|
|
|
72
72
|
Howzit.options[:for_topic] = pat
|
|
73
73
|
Howzit.options[:list_runnable] = true
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
opts.on(
|
|
76
|
+
opts.on("-T", "--task-list", "List topics containing @ directives (completion-compatible)") do
|
|
77
77
|
Howzit.options[:list_runnable] = true
|
|
78
78
|
Howzit.options[:list_runnable_titles] = true
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
opts.on(
|
|
81
|
+
opts.on("--templates", "List available templates") do
|
|
82
82
|
out = []
|
|
83
83
|
Dir.chdir(Howzit.config.template_folder)
|
|
84
|
-
Dir.glob(
|
|
85
|
-
template = File.basename(file,
|
|
84
|
+
Dir.glob("*.md").each do |file|
|
|
85
|
+
template = File.basename(file, ".md")
|
|
86
86
|
out.push(Howzit::Color.template("{Mk}template:{Yk}#{template}{x}"))
|
|
87
|
-
out.push(Howzit::Color.template(
|
|
87
|
+
out.push(Howzit::Color.template("{bk}[{bl}tasks{bk}]──────────────────────────────────────┐{x}"))
|
|
88
88
|
metadata = file.extract_metadata
|
|
89
89
|
topics = Howzit::BuildNote.new(file: file).topics
|
|
90
90
|
topics.each do |topic|
|
|
91
|
-
out.push(Howzit::Color.template(" {bk}│{bw}-{x} {bcK}#{template}:#{topic.title.sub(/^.*?:/,
|
|
91
|
+
out.push(Howzit::Color.template(" {bk}│{bw}-{x} {bcK}#{template}:#{topic.title.sub(/^.*?:/, "")}{x}"))
|
|
92
92
|
end
|
|
93
93
|
unless metadata.empty?
|
|
94
94
|
meta = []
|
|
95
|
-
meta << metadata[
|
|
96
|
-
meta << metadata[
|
|
97
|
-
out.push(Howzit::Color.template(
|
|
98
|
-
out.push(Howzit::Color.template(" {bk}│ {xw}#{meta.join(
|
|
95
|
+
meta << metadata["required"].split(/\s*,\s*/).map { |m| "*{bw}#{m}{xw}" } if metadata.key?("required")
|
|
96
|
+
meta << metadata["optional"].split(/\s*,\s*/).map(&:to_s) if metadata.key?("optional")
|
|
97
|
+
out.push(Howzit::Color.template("{bk}[{bl}meta{bk}]───────────────────────────────────────┤{x}"))
|
|
98
|
+
out.push(Howzit::Color.template(" {bk}│ {xw}#{meta.join(", ")}{x}"))
|
|
99
99
|
end
|
|
100
|
-
out.push(Howzit::Color.template(
|
|
100
|
+
out.push(Howzit::Color.template(" {bk}└───────────────────────────────────────────┘{x}"))
|
|
101
101
|
end
|
|
102
102
|
Howzit::Util.page out.join("\n")
|
|
103
103
|
Process.exit 0
|
|
104
104
|
end
|
|
105
105
|
|
|
106
|
-
opts.on(
|
|
106
|
+
opts.on("--templates-c", "List available templates in a format for completion") do
|
|
107
107
|
out = []
|
|
108
108
|
Dir.chdir(Howzit.config.template_folder)
|
|
109
|
-
Dir.glob(
|
|
110
|
-
template = File.basename(file,
|
|
109
|
+
Dir.glob("*.md").each do |file|
|
|
110
|
+
template = File.basename(file, ".md")
|
|
111
111
|
out.push(template)
|
|
112
112
|
end
|
|
113
113
|
puts out.join("\n")
|
|
114
114
|
Process.exit 0
|
|
115
115
|
end
|
|
116
116
|
|
|
117
|
-
opts.on(
|
|
117
|
+
opts.on("--title-only", "Output title only") do
|
|
118
118
|
Howzit.options[:output_title] = true
|
|
119
119
|
Howzit.options[:title_only] = true
|
|
120
120
|
end
|
|
121
121
|
|
|
122
122
|
opts.separator("\n Commands:\n\n") #=================================================================== COMMANDS
|
|
123
123
|
|
|
124
|
-
opts.on(
|
|
124
|
+
opts.on("-c", "--create", "Create a skeleton build note in the current working directory") do
|
|
125
125
|
Howzit.buildnote.create_note
|
|
126
126
|
Process.exit 0
|
|
127
127
|
end
|
|
128
128
|
|
|
129
|
-
opts.on(
|
|
129
|
+
opts.on("--config-get [KEY]", "Display the configuration settings or setting for a specific key") do |k|
|
|
130
130
|
if k.nil?
|
|
131
131
|
Howzit::Config::DEFAULTS.sort_by { |key, _| key }.each do |key, _|
|
|
132
132
|
print "#{key}: "
|
|
133
133
|
p Howzit.options[key]
|
|
134
134
|
end
|
|
135
135
|
else
|
|
136
|
-
k.sub!(/^:/,
|
|
136
|
+
k.sub!(/^:/, "")
|
|
137
137
|
if Howzit.options.key?(k.to_sym)
|
|
138
138
|
puts Howzit.options[k.to_sym]
|
|
139
139
|
else
|
|
@@ -143,12 +143,12 @@ OptionParser.new do |opts|
|
|
|
143
143
|
Process.exit 0
|
|
144
144
|
end
|
|
145
145
|
|
|
146
|
-
opts.on(
|
|
147
|
-
raise
|
|
146
|
+
opts.on("--config-set KEY=VALUE", "Set a config value (must be a valid key)") do |key|
|
|
147
|
+
raise "Argument must be KEY=VALUE" unless key =~ /\S=\S/
|
|
148
148
|
|
|
149
149
|
parts = key.split(/=/)
|
|
150
|
-
k = parts.shift.sub(/^:/,
|
|
151
|
-
v = parts.join(
|
|
150
|
+
k = parts.shift.sub(/^:/, "")
|
|
151
|
+
v = parts.join(" ")
|
|
152
152
|
|
|
153
153
|
if Howzit.options.key?(k.to_sym)
|
|
154
154
|
Howzit.options[k.to_sym] = v.to_config_value(Howzit.options[k.to_sym])
|
|
@@ -160,103 +160,103 @@ OptionParser.new do |opts|
|
|
|
160
160
|
end
|
|
161
161
|
|
|
162
162
|
desc = %(Edit buildnotes file in current working directory using default editor)
|
|
163
|
-
opts.on(
|
|
163
|
+
opts.on("-e", "--edit", desc) do
|
|
164
164
|
Howzit.buildnote.edit
|
|
165
165
|
Process.exit 0
|
|
166
166
|
end
|
|
167
167
|
|
|
168
|
-
opts.on(
|
|
168
|
+
opts.on("--edit-config", "Edit configuration file using default editor") do
|
|
169
169
|
Howzit.config.editor
|
|
170
170
|
Process.exit 0
|
|
171
171
|
end
|
|
172
172
|
|
|
173
|
-
opts.on(
|
|
173
|
+
opts.on("--edit-template NAME", "Create or edit a template") do |template|
|
|
174
174
|
Howzit.buildnote.edit_template(template)
|
|
175
175
|
Process.exit 0
|
|
176
176
|
end
|
|
177
177
|
|
|
178
|
-
opts.on(
|
|
178
|
+
opts.on("--grep PATTERN", "Display sections matching a search pattern") do |pat|
|
|
179
179
|
Howzit.options[:grep] = pat
|
|
180
180
|
end
|
|
181
181
|
|
|
182
|
-
opts.on(
|
|
182
|
+
opts.on("--hook", "Copy a link to the build note file, ready for pasting into Hook.app or other notes") do
|
|
183
183
|
Howzit.buildnote.hook
|
|
184
184
|
Process.exit 0
|
|
185
185
|
end
|
|
186
186
|
|
|
187
|
-
opts.on(
|
|
187
|
+
opts.on("-r", "--run", "Execute @run, @open, and/or @copy commands for given topic") do
|
|
188
188
|
Howzit.options[:run] = true
|
|
189
189
|
end
|
|
190
190
|
|
|
191
|
-
opts.on(
|
|
191
|
+
opts.on("-s", "--select", "Select topic from menu") do
|
|
192
192
|
Howzit.options[:choose] = true
|
|
193
193
|
end
|
|
194
194
|
|
|
195
195
|
opts.separator("\n Formatting:\n\n") #=================================================================== FORMATTING
|
|
196
196
|
|
|
197
|
-
opts.on(
|
|
197
|
+
opts.on("--[no-]color", "Colorize output (default on)") do |c|
|
|
198
198
|
Howzit.options[:color] = c
|
|
199
199
|
Howzit.options[:highlight] = false unless c
|
|
200
200
|
end
|
|
201
201
|
|
|
202
|
-
opts.on(
|
|
203
|
-
"Formatting style for topic titles (#{HEADER_FORMAT_OPTIONS.join(
|
|
202
|
+
opts.on("--header-format TYPE", HEADER_FORMAT_OPTIONS,
|
|
203
|
+
"Formatting style for topic titles (#{HEADER_FORMAT_OPTIONS.join(", ")})") do |t|
|
|
204
204
|
Howzit.options[:header_format] = t
|
|
205
205
|
end
|
|
206
206
|
|
|
207
|
-
opts.on(
|
|
207
|
+
opts.on("--[no-]md-highlight", "Highlight Markdown syntax (default on), requires mdless or mdcat") do |m|
|
|
208
208
|
Howzit.options[:highlight] = Howzit.options[:color] ? m : false
|
|
209
209
|
end
|
|
210
210
|
|
|
211
|
-
opts.on(
|
|
211
|
+
opts.on("--[no-]pager", "Paginate output (default on)") do |p|
|
|
212
212
|
Howzit.options[:paginate] = p
|
|
213
213
|
end
|
|
214
214
|
|
|
215
|
-
opts.on(
|
|
215
|
+
opts.on("--show-code", "Display the content of fenced run blocks") do
|
|
216
216
|
Howzit.options[:show_all_code] = true
|
|
217
217
|
end
|
|
218
218
|
|
|
219
|
-
opts.on(
|
|
219
|
+
opts.on("-t", "--title", "Output title with build notes") do
|
|
220
220
|
Howzit.options[:output_title] = true
|
|
221
221
|
end
|
|
222
222
|
|
|
223
|
-
opts.on(
|
|
223
|
+
opts.on("-w", "--wrap COLUMNS", "Wrap to specified width (default 80, 0 to disable)") do |w|
|
|
224
224
|
Howzit.options[:wrap] = w.to_i
|
|
225
225
|
end
|
|
226
226
|
|
|
227
227
|
opts.separator("\n Logging:\n\n") #=================================================================== LOGGING
|
|
228
228
|
|
|
229
|
-
opts.on(
|
|
229
|
+
opts.on("-d", "--debug", "Show debug messages (and all messages)") do
|
|
230
230
|
Howzit.options[:log_level] = 0
|
|
231
231
|
Howzit.console.reset_level
|
|
232
232
|
end
|
|
233
233
|
|
|
234
|
-
opts.on(
|
|
234
|
+
opts.on("-q", "--quiet", "Silence info message") do
|
|
235
235
|
Howzit.options[:log_level] = 4
|
|
236
236
|
Howzit.console.reset_level
|
|
237
237
|
end
|
|
238
238
|
|
|
239
|
-
opts.on(
|
|
239
|
+
opts.on("--verbose", "Show all messages") do
|
|
240
240
|
Howzit.options[:log_level] = 1
|
|
241
241
|
Howzit.console.reset_level
|
|
242
242
|
end
|
|
243
243
|
|
|
244
244
|
opts.separator("\n Misc:\n\n") #=================================================================== MISC
|
|
245
245
|
|
|
246
|
-
opts.on(
|
|
246
|
+
opts.on("-h", "--help", "Display this screen") do
|
|
247
247
|
Howzit::Util.page opts.to_s
|
|
248
248
|
Process.exit 0
|
|
249
249
|
end
|
|
250
250
|
|
|
251
|
-
opts.on(
|
|
251
|
+
opts.on("-v", "--version", "Display version number") do
|
|
252
252
|
puts "#{File.basename(__FILE__)} v#{Howzit::VERSION}"
|
|
253
253
|
Process.exit 0
|
|
254
254
|
end
|
|
255
255
|
end.parse!(args)
|
|
256
256
|
|
|
257
|
-
trap(
|
|
257
|
+
trap("INT") do
|
|
258
258
|
puts
|
|
259
|
-
puts
|
|
259
|
+
puts "Cancelled"
|
|
260
260
|
Process.exit 0
|
|
261
261
|
end
|
|
262
262
|
|
data/howzit.gemspec
CHANGED
|
@@ -16,7 +16,9 @@ Gem::Specification.new do |spec|
|
|
|
16
16
|
spec.homepage = 'https://github.com/ttscoff/howzit'
|
|
17
17
|
spec.license = 'MIT'
|
|
18
18
|
|
|
19
|
-
spec.files = `git ls-files`.split(
|
|
19
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |path|
|
|
20
|
+
path.split('/').any? { |segment| segment.start_with?('.') } || path.end_with?('.bak')
|
|
21
|
+
end
|
|
20
22
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
|
21
23
|
spec.test_files = spec.files.grep(%r{^(features|spec|test)/})
|
|
22
24
|
spec.require_paths = ['lib']
|