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 +4 -4
- data/Fastfile +3 -0
- data/README.md +1 -0
- data/docs/command_line.md +1 -0
- data/docs/editors-integration.md +46 -0
- data/docs/shortcuts.md +288 -0
- data/docs/videos.md +12 -0
- data/fast.gemspec +1 -0
- data/lib/fast.rb +44 -22
- data/lib/fast/cli.rb +35 -16
- data/lib/fast/shortcut.rb +1 -1
- data/lib/fast/version.rb +1 -1
- data/mkdocs.yml +3 -0
- metadata +21 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d1ae41b9a66311eb3308fd3ca3f69f5a06943a337f9907d502f1a2ed27342a46
|
4
|
+
data.tar.gz: 80e545ae2769ab27ba39d8338b57c60626ca3f79ec5e73139c12f3cb01dfd5fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
data/docs/command_line.md
CHANGED
@@ -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).
|
data/docs/shortcuts.md
ADDED
@@ -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
|
+
|
data/docs/videos.md
ADDED
@@ -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>
|
data/fast.gemspec
CHANGED
data/lib/fast.rb
CHANGED
@@ -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
|
-
|
113
|
-
|
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
|
-
|
122
|
-
|
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
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
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
|
-
#
|
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
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
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)
|
data/lib/fast/cli.rb
CHANGED
@@ -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
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
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
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
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(
|
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
|
-
|
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
|
data/lib/fast/shortcut.rb
CHANGED
@@ -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
|
data/lib/fast/version.rb
CHANGED
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.
|
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
|
+
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
|
-
|
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.'
|