ffast 0.1.6 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c664b4d8bafbac99cd9814bcdf77e730184c6e9a38a01ab52d21369bc9c52f8d
4
- data.tar.gz: 3f761262fc7db1a9ab856fcdab4bfe1580187d882f253f03cd82138b745a43d9
3
+ metadata.gz: d1ae41b9a66311eb3308fd3ca3f69f5a06943a337f9907d502f1a2ed27342a46
4
+ data.tar.gz: 80e545ae2769ab27ba39d8338b57c60626ca3f79ec5e73139c12f3cb01dfd5fb
5
5
  SHA512:
6
- metadata.gz: 742d1f586ede35f47ecdcd27013d9e2082641a7809edc6ea43e1538954a805d9d8aadd2f3c6772161bcad2df6223ba2920a71d745a067e3a6ca91c8ef220c2f4
7
- data.tar.gz: 7cb8e4d954d2ecea9e8a5d3f6f94a7b08ecaed80df1b6ee72bcb8e2b0ca58ce1fd20a84166f884fe8d38f4c692ae1da129ec3276a46d3f6a820efde903e830fd
6
+ metadata.gz: fbcb874fb1c2916d0fa89d687fd9e320f248c8cc64c5193244b8d007b39cffb86b23db2ff7c3134c4d43baba1d4d99b6526831a20b3c630867691d5076ae33bc
7
+ data.tar.gz: de6c3a1e706f6a3e39791a413584dc227af3ee8810628145b0844d9b4d2ac1f9d7f631c9db859a7cb6d8c7f56313b3f0aff2be4b9868627c31ece3924e79379c
data/Fastfile CHANGED
@@ -8,6 +8,9 @@
8
8
  # Let's say you'd like to show the version that is over the version file
9
9
  Fast.shortcut(:version, '(casgn nil VERSION (str _))', 'lib/fast/version.rb')
10
10
 
11
+ # Show all classes that inherits Fast::Find
12
+ Fast.shortcut(:finders, '(class ... (const nil Find)', 'lib')
13
+
11
14
  # You can run shortcuts appending a dot to the shortcut.
12
15
  # $ fast .version
13
16
  # # lib/fast/version.rb:4
data/README.md CHANGED
@@ -421,6 +421,7 @@ The CLI tool takes the following flags
421
421
  - Use `--pry` to jump debugging the first result with pry
422
422
  - Use `-c` to search from code example
423
423
  - Use `-s` to search similar code
424
+ - Use `-p` or `--parallel` to parallelize the search
424
425
 
425
426
  ### Define your `Fastfile`
426
427
 
@@ -11,6 +11,7 @@ $ fast '(def match?)' lib/fast.rb
11
11
  - Use `--pry` to jump debugging the first result with pry
12
12
  - Use `-c` to search from code example
13
13
  - Use `-s` to search similar code
14
+ - Use `-p` to or `--parallel` to use multi core search
14
15
 
15
16
  ## `--pry`
16
17
 
@@ -0,0 +1,46 @@
1
+ # Editors' integration
2
+
3
+ We don't have any proper integration or official plugins for editors yet.
4
+
5
+ Here are a few ideas you can use to make your own flow.
6
+
7
+ ## Vim
8
+
9
+ Split terminal vertically and open fast focused on build the expression.
10
+
11
+ ```vim
12
+ nnoremap <Leader>ff :vsplit \| terminal fast "()" % <Left><Left><Left><Left><Left>
13
+ ```
14
+
15
+ Or you can build a function:
16
+
17
+ ```vim
18
+ function! s:Fast(args)
19
+ let cmd = ''
20
+ if !empty(b:ruby_project_root)
21
+ let cmd .= 'cd ' . b:ruby_project_root . ' && '
22
+ endif
23
+
24
+ let cmd .= 'fast --no-color ' . a:args
25
+
26
+ let custom_maker = neomake#utils#MakerFromCommand(cmd)
27
+ let custom_maker.name = cmd
28
+ let custom_maker.cwd = b:ruby_project_root
29
+ let custom_maker.remove_invalid_entries = 0
30
+ " e.g.:
31
+ " # path/to/file.rb:1141
32
+ " my_method(
33
+ " :boom,
34
+ " arg1: 1,
35
+ " )
36
+ " %W# %f:%l -> start a multiline warning when the line matches '# path/file.rb:1234'
37
+ " %-Z# end multiline warning on the next line that starts with '#'
38
+ " %C%m continued multiline warning message
39
+ let custom_maker.errorformat = '%W# %f:%l, %-Z#, %C%m'
40
+ let enabled_makers = [custom_maker]
41
+ update | call neomake#Make(0, enabled_makers) | echom "running: " . cmd
42
+ endfunction
43
+ command! -complete=file -nargs=1 Fast call s:Fast(<q-args>)
44
+ ```
45
+
46
+ Check the conversation about vim integration [here](https://github.com/jonatas/fast/pull/16#issuecomment-555115606).
@@ -0,0 +1,288 @@
1
+ # Shortcuts
2
+
3
+ Shortcuts are defined on a `Fastfile` inside any ruby project.
4
+
5
+ !!!info "Use `~/Fastfile`"
6
+ You can also add one extra in your `$HOME` if you want to have something loaded always.
7
+
8
+ By default, the command line interface does not load any `Fastfile` if the
9
+ first param is not a shortcut. It should start with `.`.
10
+
11
+ I'm building several researches and I'll make the examples open here to show
12
+ several interesting cases in action.
13
+
14
+ ## Rails: Show validations from models
15
+
16
+ If the shortcut does not define a block, it works as a holder for arguments from
17
+ the command line.
18
+
19
+ Let's say you always use `fast "(send nil {validate validates})" app/models` to
20
+ check validations in the models. You can define a shortcut to hold the args and
21
+ avoid retyping long lines:
22
+
23
+ ```ruby
24
+ # Show validations from app/models
25
+ Fast.shortcut(:validations, "(send nil {validate validates})", "app/models")
26
+ ```
27
+ And you can reuse the search with the shortcut starting with a `.`:
28
+
29
+ ```
30
+ fast .validations
31
+ ```
32
+ And it will also accept params if you want to filter a specific file:
33
+
34
+ ```
35
+ fast .validations app/models/user.rb
36
+ ```
37
+
38
+ !!! info "Note that you can also use flags in the command line shortcuts"
39
+
40
+ Let's say you also want to use `fast --headless` you can add it to the params:
41
+
42
+ > Fast.shortcut(:validations, "(send nil {validate validates})", "app/models", "--headless")
43
+
44
+ ## Automated Refactor: Bump version
45
+
46
+ Let's start with a [real usage](https://github.com/jonatas/fast/blob/master/Fastfile#L20-L34)
47
+ to bump a new version of the gem.
48
+
49
+ ```ruby
50
+ Fast.shortcut :bump_version do
51
+ rewrite_file('(casgn nil VERSION (str _)', 'lib/fast/version.rb') do |node|
52
+ target = node.children.last.loc.expression
53
+ pieces = target.source.split('.').map(&:to_i)
54
+ pieces.reverse.each_with_index do |fragment, i|
55
+ if fragment < 9
56
+ pieces[-(i + 1)] = fragment + 1
57
+ break
58
+ else
59
+ pieces[-(i + 1)] = 0
60
+ end
61
+ end
62
+ replace(target, "'#{pieces.join('.')}'")
63
+ end
64
+ end
65
+ ```
66
+
67
+ And then the change is done in the `lib/fast/version.rb`:
68
+
69
+ ```diff
70
+ module Fast
71
+ - VERSION = '0.1.6'
72
+ + VERSION = '0.1.7'
73
+ end
74
+ ```
75
+
76
+ ## List Shortcuts
77
+
78
+ As the interface is very rudimentar, let's build a shortcut to print what
79
+ shortcuts are available. This is a good one to your `$HOME/Fastfile`:
80
+
81
+ ```ruby
82
+ # List all shortcut with comments
83
+ Fast.shortcut :shortcuts do
84
+ fast_files.each do |file|
85
+ lines = File.readlines(file).map{|line|line.chomp.gsub(/\s*#/,'').strip}
86
+ result = capture_file('(send ... shortcut $(sym _', file)
87
+ result = [result] unless result.is_a?Array
88
+ result.each do |capture|
89
+ target = capture.loc.expression
90
+ puts "fast .#{target.source[1..-1].ljust(30)} # #{lines[target.line-2]}"
91
+ end
92
+ end
93
+ end
94
+ ```
95
+
96
+ And using it on `fast` project that loads both `~/Fastfile` and the Fastfile from the project:
97
+
98
+ ```
99
+ fast .version # Let's say you'd like to show the version that is over the version file
100
+ fast .parser # Simple shortcut that I used often to show how the expression parser works
101
+ fast .bump_version # Use `fast .bump_version` to rewrite the version file
102
+ fast .shortcuts # List all shortcut with comments
103
+ ```
104
+
105
+ ## RSpec: Find unused shared contexts
106
+
107
+ If you build shared contexts often, probably you can forget some left overs.
108
+
109
+ The objective of the shortcut is find leftovers from shared contexts.
110
+
111
+ First, the objective is capture all names of the `RSpec.shared_context` or
112
+ `shared_context` declared in the `spec/support` folder.
113
+
114
+ ```ruby
115
+ Fast.capture_all('(block (send {nil,_} shared_context (str $_)))', Fast.ruby_files_from('spec/support'))
116
+ ```
117
+
118
+ Then, we need to check all the specs and search for `include_context` usages to
119
+ confirm if all defined contexts are being used:
120
+
121
+ ```ruby
122
+ specs = Fast.ruby_files_from('spec').select{|f|f !~ %r{spec/support/}}
123
+ Fast.search_all("(send nil include_context (str #register_usage)", specs)
124
+ ```
125
+
126
+ Note that we created a new reference to `#register_usage` and we need to define the method too:
127
+
128
+
129
+ ```ruby
130
+ @used = []
131
+ def register_usage context_name
132
+ @used << context_name
133
+ end
134
+ ```
135
+
136
+ Wrapping up everything in a shortcut:
137
+
138
+ ```ruby
139
+ # Show unused shared contexts
140
+ Fast.shortcut(:unused_shared_contexts) do
141
+ puts "Checking shared contexts"
142
+ Kernel.class_eval do
143
+ @used = []
144
+ def register_usage context_name
145
+ @used << context_name
146
+ end
147
+ def show_report! defined_contexts
148
+ unused = defined_contexts.values.flatten - @used
149
+ if unused.any?
150
+ puts "Unused shared contexts", unused
151
+ else
152
+ puts "Good job! all the #{defined_contexts.size} contexts are used!"
153
+ end
154
+ end
155
+ end
156
+ specs = ruby_files_from('spec/').select{|f|f !~ %r{spec/support/}}
157
+ search_all("(send nil include_context (str #register_usage)", specs)
158
+ defined_contexts = capture_all('(block (send {nil,_} shared_context (str $_)))', ruby_files_from('spec'))
159
+ Kernel.public_send(:show_report!, defined_contexts)
160
+ end
161
+ ```
162
+
163
+ !!! faq "Why `#register_usage` is defined on the `Kernel`?"
164
+ Yes! note that the `#register_usage` was forced to be inside `Kernel`
165
+ because of the `shortcut` block that takes the `Fast` context to be easy
166
+ to access in the default functions. As I can define multiple shortcuts
167
+ I don't want to polute my Kernel module with other methods that are not useful.
168
+
169
+
170
+ ## RSpec: Remove unused let
171
+
172
+ !!! hint "First shortcut with experiments"
173
+ If you're not familiar with automated experiments, you can read about it [here](/experiments).
174
+
175
+ The current scenario is similar in terms of search with the previous one, but more advanced
176
+ because we're going to introduce automated refactoring.
177
+
178
+ The idea is simple, if it finds a `let` in a RSpec scenario that is not referenced, it tries to experimentally remove the `let` and run the tests:
179
+
180
+ ```ruby
181
+ # Experimental remove `let` that are not referenced in the spec
182
+ Fast.shortcut(:exp_remove_let) do
183
+ require 'fast/experiment'
184
+ Kernel.class_eval do
185
+ file = ARGV.last
186
+
187
+ defined_lets = Fast.capture_file('(block (send nil let (sym $_)))', file).uniq
188
+ @unreferenced= defined_lets.select do |identifier|
189
+ Fast.search_file("(send nil #{identifier})", file).empty?
190
+ end
191
+
192
+ def unreferenced_let?(identifier)
193
+ @unreferenced.include? identifier
194
+ end
195
+ end
196
+
197
+ experiment('RSpec/RemoveUnreferencedLet') do
198
+ lookup ARGV.last
199
+ search '(block (send nil let (sym #unreferenced_let?)))'
200
+ edit { |node| remove(node.loc.expression) }
201
+ policy { |new_file| system("bundle exec rspec --fail-fast #{new_file}") }
202
+ end.run
203
+ end
204
+ ```
205
+
206
+ And it will run with a single file from command line:
207
+
208
+ ```
209
+ fast .exp_remove_let spec/my_file_spec.rb
210
+ ```
211
+
212
+ ## FactoryBot: Replace `create` with `build_stubbed`
213
+
214
+ For performance reasons, if we can avoid touching the database the test will
215
+ always be faster.
216
+
217
+ ```ruby
218
+ # Experimental switch from `create` to `build_stubbed`
219
+ Fast.shortcut(:exp_build_stubbed) do
220
+ require 'fast/experiment'
221
+ Fast.experiment('FactoryBot/UseBuildStubbed') do
222
+ lookup ARGV.last
223
+ search '(send nil create)'
224
+ edit { |node| replace(node.loc.selector, 'build_stubbed') }
225
+ policy { |new_file| system("bundle exec rspec --fail-fast #{new_file}") }
226
+ end.run
227
+ end
228
+ ```
229
+ ## RSpec: Use `let_it_be` instead of `let`
230
+
231
+ The `let_it_be` is a simple helper from
232
+ [TestProf](https://test-prof.evilmartians.io/#/let_it_be) gem that can speed up
233
+ the specs by caching some factories using like a `before_all` approach.
234
+
235
+ This experiment hunts for `let(...) { create(...) }` and switch the `let` to
236
+ `let_it_be`:
237
+
238
+ ```ruby
239
+ # Experimental replace `let(_)` with `let_it_be` case it calls `create` inside the block
240
+ Fast.shortcut(:exp_let_it_be) do
241
+ require 'fast/experiment'
242
+ Fast.experiment('FactoryBot/LetItBe') do
243
+ lookup ARGV.last
244
+ search '(block (send nil let (sym _)) (args) (send nil create))'
245
+ edit { |node| replace(node.children.first.loc.selector, 'let_it_be') }
246
+ policy { |new_file| system("bin/spring rspec --fail-fast #{new_file}") }
247
+ end.run
248
+ end
249
+ ```
250
+
251
+ ## RSpec: Remove `before` or `after` blocks
252
+
253
+ From time to time, we forget some left overs like `before` or `after` blocks
254
+ that even removing from the code, the tests still passes. This experiment
255
+ removes the before/after blocks and check if the test passes.
256
+
257
+ ```ruby
258
+ # Experimental remove `before` or `after` blocks.
259
+ Fast.shortcut(:exp_remove_before_after) do
260
+ require 'fast/experiment'
261
+ Fast.experiment('RSpec/RemoveBeforeAfter') do
262
+ lookup ARGV.last
263
+ search '(block (send nil {before after}))'
264
+ edit { |node| remove(node.loc.expression) }
265
+ policy { |new_file| system("bin/spring rspec --fail-fast #{new_file}") }
266
+ end.run
267
+ end
268
+ ```
269
+
270
+ ## RSpec: Show message chains
271
+
272
+ I often forget the syntax and need to search for message chains on specs, so I
273
+ created an shortcut for it.
274
+
275
+ ```ruby
276
+ # Show RSpec message chains
277
+ Fast.shortcut(:message_chains, '^^(send nil receive_message_chain)', 'spec')
278
+ ```
279
+
280
+ ## RSpec: Show nested assertions
281
+
282
+ I love to use nested assertions and I often need examples to refer to them:
283
+
284
+ ```ruby
285
+ # Show RSpec nested assertions with .and
286
+ Fast.shortcut(:nested_assertions, '^^(send ... and)', 'spec')
287
+ ```
288
+
@@ -0,0 +1,12 @@
1
+ # Videos
2
+
3
+ - Grepping Ruby code like a boss: [RubyConf Brazil 2019 (Portuguese)](https://www.eventials.com/locaweb/jonatas-paganini-live-coding-grepping-ruby-code-like-a-boss/#_=_)
4
+
5
+ - Introduction to [inline code](https://www.youtube.com/watch?v=KQXglNLUv7o).
6
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/KQXglNLUv7o" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
7
+
8
+ - [Making local variables inline](https://www.youtube.com/watch?v=JD44nhegCRs)
9
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/YN0s9kV1A2A" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
10
+
11
+ - [Making methods inline](https://www.youtube.com/watch?v=JD44nhegCRs)
12
+ <iframe width="560" height="315" src="https://www.youtube.com/embed/YN0s9kV1A2A" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.add_dependency 'astrolabe'
28
28
  spec.add_dependency 'coderay'
29
+ spec.add_dependency 'parallel'
29
30
  spec.add_dependency 'parser'
30
31
  spec.add_dependency 'pry'
31
32
 
@@ -108,25 +108,50 @@ module Fast
108
108
  # @param [String] pattern
109
109
  # @param [Array<String>] *locations where to search. Default is '.'
110
110
  # @return [Hash<String,Array<Astrolabe::Node>>] with files and results
111
- def search_all(pattern, locations = ['.'])
112
- search_pattern = method(:search_file).curry.call(pattern)
113
- group_results(search_pattern, locations)
111
+ def search_all(pattern, locations = ['.'], parallel: true, on_result: nil)
112
+ group_results(build_grouped_search(:search_file, pattern, on_result),
113
+ locations, parallel: parallel)
114
114
  end
115
115
 
116
116
  # Capture with pattern on a directory or multiple files
117
117
  # @param [String] pattern
118
118
  # @param [Array<String>] locations where to search. Default is '.'
119
119
  # @return [Hash<String,Object>] with files and captures
120
- def capture_all(pattern, locations = ['.'])
121
- capture_pattern = method(:capture_file).curry.call(pattern)
122
- group_results(capture_pattern, locations)
120
+ def capture_all(pattern, locations = ['.'], parallel: true, on_result: nil)
121
+ group_results(build_grouped_search(:capture_file, pattern, on_result),
122
+ locations, parallel: parallel)
123
+ end
124
+
125
+ # @return [Proc] binding `pattern` argument from a given `method_name`.
126
+ # @param [Symbol] method_name with `:capture_file` or `:search_file`
127
+ # @param [String] pattern to match in a search to any file
128
+ # @param [Proc] on_result is a callback that can be notified soon it matches
129
+ def build_grouped_search(method_name, pattern, on_result)
130
+ search_pattern = method(method_name).curry.call(pattern)
131
+ proc do |file|
132
+ results = search_pattern.call(file)
133
+ next if results.nil? || results.empty?
134
+
135
+ on_result&.(file, results)
136
+ { file => results }
137
+ end
123
138
  end
124
139
 
125
- def group_results(search_pattern, locations)
126
- ruby_files_from(*locations)
127
- .map { |f| { f => search_pattern.call(f) } }
128
- .reject { |results| results.values.all?(&:empty?) }
129
- .inject(&:merge!)
140
+ # Compact grouped results by file allowing parallel processing.
141
+ # @param [Proc] group_files allows to define a search that can be executed
142
+ # parallel or not.
143
+ # @param [Proc] on_result allows to define a callback for fast feedback
144
+ # while it process several locations in parallel.
145
+ # @param [Boolean] parallel runs the `group_files` in parallel
146
+ # @return [Hash[String, Array]] with files and results
147
+ def group_results(group_files, locations, parallel: true)
148
+ files = ruby_files_from(*locations)
149
+ if parallel
150
+ require 'parallel' unless defined?(Parallel)
151
+ Parallel.map(files, &group_files)
152
+ else
153
+ files.map(&group_files)
154
+ end.compact.inject(&:merge!)
130
155
  end
131
156
 
132
157
  # Capture elements from searches in files. Keep in mind you need to use `$`
@@ -154,19 +179,16 @@ module Fast
154
179
  end
155
180
  end
156
181
 
157
- # Return only captures from a search
182
+ # Only captures from a search
158
183
  # @return [Array<Object>] with all captured elements.
159
- # @return [Object] with single element when single capture.
160
184
  def capture(pattern, node)
161
- res = if (match = match?(pattern, node))
162
- match == true ? node : match
163
- else
164
- node.each_child_node
165
- .flat_map { |child| capture(pattern, child) }
166
- .compact.flatten
167
- end
168
- res = [res] unless res.is_a?(Array)
169
- res.one? ? res.first : res
185
+ if (match = match?(pattern, node))
186
+ match == true ? node : match
187
+ else
188
+ node.each_child_node
189
+ .flat_map { |child| capture(pattern, child) }
190
+ .compact.flatten
191
+ end
170
192
  end
171
193
 
172
194
  def expression(string)
@@ -69,6 +69,10 @@ module Fast
69
69
  @show_sexp = true
70
70
  end
71
71
 
72
+ opts.on('-p', '--parallel', 'Paralelize search') do
73
+ @parallel = true
74
+ end
75
+
72
76
  opts.on('--captures', 'Print only captures of the patterns and skip node results') do
73
77
  @captures = true
74
78
  end
@@ -129,6 +133,8 @@ module Fast
129
133
 
130
134
  # Show help or search for node patterns
131
135
  def run!
136
+ raise 'pry and parallel options are incompatible :(' if @parallel && @pry
137
+
132
138
  if @help || @files.empty? && @pattern.nil?
133
139
  puts option_parser.help
134
140
  else
@@ -137,6 +143,7 @@ module Fast
137
143
  end
138
144
 
139
145
  # Create fast expression from node pattern using the command line
146
+ # @return [Array<Fast::Find>] with the expression from string.
140
147
  def expression
141
148
  Fast.expression(@pattern)
142
149
  end
@@ -146,24 +153,29 @@ module Fast
146
153
  # If capture option is enabled it will only print the captures, otherwise it
147
154
  # prints all the results.
148
155
  def search
149
- if debug_mode?
150
- Fast.debug { execute_search }
151
- else
152
- execute_search do |file, results|
153
- results.each do |result|
154
- binding.pry if @pry # rubocop:disable Lint/Debugger
155
- report(result, file)
156
- end
156
+ return Fast.debug(&method(:execute_search)) if debug_mode?
157
+
158
+ execute_search do |file, results|
159
+ results.each do |result|
160
+ binding.pry if @pry # rubocop:disable Lint/Debugger
161
+ report(file, result)
157
162
  end
158
163
  end
159
164
  end
160
165
 
161
- def execute_search
162
- method_name = @captures ? :capture_all : :search_all
163
- (Fast.public_send(method_name, expression, @files) || []).each do |file, results|
164
- results = [results] unless results.is_a?(Array)
165
- yield file, results
166
- end
166
+ # Executes search for all files yielding the results
167
+ # @yieldparam [String, Array] with file and respective search results
168
+ def execute_search(&on_result)
169
+ Fast.public_send(search_method_name,
170
+ expression,
171
+ @files,
172
+ parallel: parallel?,
173
+ on_result: on_result)
174
+ end
175
+
176
+ # @return [Symbol] with `:capture_all` or `:search_all` depending the command line options
177
+ def search_method_name
178
+ @captures ? :capture_all : :search_all
167
179
  end
168
180
 
169
181
  # @return [Boolean] true when "-d" or "--debug" option is passed
@@ -176,9 +188,13 @@ module Fast
176
188
  puts(info) if debug_mode?
177
189
  end
178
190
 
191
+ def parallel?
192
+ @parallel == true
193
+ end
194
+
179
195
  # Report results using the actual options binded from command line.
180
196
  # @see Fast.report
181
- def report(result, file)
197
+ def report(file, result)
182
198
  Fast.report(result, file: file, show_sexp: @show_sexp, headless: @headless, colorize: @colorize)
183
199
  end
184
200
 
@@ -198,7 +214,10 @@ module Fast
198
214
  # Prints available shortcuts as extra help and exit with code 1.
199
215
  def exit_shortcut_not_found(name)
200
216
  puts "Shortcut \033[1m#{name}\033[0m not found :("
201
- puts "Available shortcuts are: #{Fast.shortcuts.keys.join(', ')}." if Fast.shortcuts.any?
217
+ if Fast.shortcuts.any?
218
+ puts "Available shortcuts are: #{Fast.shortcuts.keys.join(', ')}."
219
+ Fast.load_fast_files!
220
+ end
202
221
  exit 1
203
222
  end
204
223
  end
@@ -66,7 +66,7 @@ module Fast
66
66
  # the options from previous alias and replacing the files with the
67
67
  # @param [Array] extra_args
68
68
  def merge_args(extra_args)
69
- [params[0], *options, *extra_args]
69
+ [params[0], *options, *extra_args.select(&File.method(:exists?))]
70
70
  end
71
71
 
72
72
  # If the shortcut was defined with a single block and no extra arguments, it
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Fast
4
- VERSION = '0.1.6'
4
+ VERSION = '0.1.7'
5
5
  end
data/mkdocs.yml CHANGED
@@ -18,5 +18,8 @@ nav:
18
18
  - Syntax: syntax.md
19
19
  - Command Line: command_line.md
20
20
  - Experiments: experiments.md
21
+ - Shortcuts: shortcuts.md
21
22
  - Code Similarity: similarity_tutorial.md
22
23
  - Pry Integration: pry-integration.md
24
+ - Editors' Integration: editors-integration.md
25
+ - Videos: videos.md
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ffast
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jônatas Davi Paganini
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-11-18 00:00:00.000000000 Z
11
+ date: 2019-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: astrolabe
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: parallel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: parser
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -247,11 +261,14 @@ files:
247
261
  - bin/fast-experiment
248
262
  - bin/setup
249
263
  - docs/command_line.md
264
+ - docs/editors-integration.md
250
265
  - docs/experiments.md
251
266
  - docs/index.md
252
267
  - docs/pry-integration.md
268
+ - docs/shortcuts.md
253
269
  - docs/similarity_tutorial.md
254
270
  - docs/syntax.md
271
+ - docs/videos.md
255
272
  - examples/build_stubbed_and_let_it_be_experiment.rb
256
273
  - examples/experimental_replacement.rb
257
274
  - examples/find_usage.rb
@@ -291,7 +308,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
291
308
  - !ruby/object:Gem::Version
292
309
  version: '0'
293
310
  requirements: []
294
- rubygems_version: 3.0.3
311
+ rubyforge_project:
312
+ rubygems_version: 2.7.6.2
295
313
  signing_key:
296
314
  specification_version: 4
297
315
  summary: 'FAST: Find by AST.'