ffast 0.1.5 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +114 -2
- data/.sourcelevel.yml +2 -0
- data/.travis.yml +2 -2
- data/Fastfile +3 -0
- data/README.md +10 -5
- data/docs/command_line.md +1 -0
- data/docs/editors-integration.md +46 -0
- data/docs/ideas.md +80 -0
- data/docs/index.md +5 -0
- data/docs/research.md +93 -0
- data/docs/shortcuts.md +323 -0
- data/docs/videos.md +16 -0
- data/fast.gemspec +6 -4
- data/lib/fast.rb +135 -40
- data/lib/fast/cli.rb +61 -23
- data/lib/fast/experiment.rb +1 -2
- data/lib/fast/git.rb +101 -0
- data/lib/fast/shortcut.rb +6 -9
- data/lib/fast/version.rb +1 -1
- data/mkdocs.yml +5 -0
- metadata +54 -13
data/lib/fast/cli.rb
CHANGED
@@ -36,12 +36,16 @@ module Fast
|
|
36
36
|
# @param headless [Boolean] Skip printing the file name and line before content
|
37
37
|
# @example
|
38
38
|
# Fast.highlight(Fast.search(...))
|
39
|
-
def report(result, show_sexp: false, file: nil, headless: false, colorize: true)
|
39
|
+
def report(result, show_link: false, show_sexp: false, file: nil, headless: false, bodyless: false, colorize: true) # rubocop:disable Metrics/ParameterLists
|
40
40
|
if file
|
41
41
|
line = result.loc.expression.line if result.is_a?(Parser::AST::Node)
|
42
|
-
|
42
|
+
if show_link
|
43
|
+
puts(result.link)
|
44
|
+
elsif !headless
|
45
|
+
puts(highlight("# #{file}:#{line}", colorize: colorize))
|
46
|
+
end
|
43
47
|
end
|
44
|
-
puts
|
48
|
+
puts(highlight(result, show_sexp: show_sexp, colorize: colorize)) unless bodyless
|
45
49
|
end
|
46
50
|
|
47
51
|
# Command Line Interface for Fast
|
@@ -69,6 +73,15 @@ module Fast
|
|
69
73
|
@show_sexp = true
|
70
74
|
end
|
71
75
|
|
76
|
+
opts.on('--link', 'Print link to repository URL instead of code') do
|
77
|
+
require 'fast/git'
|
78
|
+
@show_link = true
|
79
|
+
end
|
80
|
+
|
81
|
+
opts.on('-p', '--parallel', 'Paralelize search') do
|
82
|
+
@parallel = true
|
83
|
+
end
|
84
|
+
|
72
85
|
opts.on('--captures', 'Print only captures of the patterns and skip node results') do
|
73
86
|
@captures = true
|
74
87
|
end
|
@@ -77,6 +90,10 @@ module Fast
|
|
77
90
|
@headless = true
|
78
91
|
end
|
79
92
|
|
93
|
+
opts.on('--bodyless', 'Print results without the code details') do
|
94
|
+
@bodyless = true
|
95
|
+
end
|
96
|
+
|
80
97
|
opts.on('--pry', 'Jump into a pry session with results') do
|
81
98
|
@pry = true
|
82
99
|
require 'pry'
|
@@ -112,12 +129,13 @@ module Fast
|
|
112
129
|
end
|
113
130
|
|
114
131
|
def replace_args_with_shortcut(args)
|
115
|
-
shortcut = find_shortcut args.first[1
|
132
|
+
shortcut = find_shortcut args.first[1..]
|
133
|
+
|
116
134
|
if shortcut.single_run_with_block?
|
117
135
|
shortcut.run
|
118
136
|
exit
|
119
137
|
else
|
120
|
-
args.one? ? shortcut.args : shortcut.merge_args(args[1
|
138
|
+
args.one? ? shortcut.args : shortcut.merge_args(args[1..])
|
121
139
|
end
|
122
140
|
end
|
123
141
|
|
@@ -129,6 +147,8 @@ module Fast
|
|
129
147
|
|
130
148
|
# Show help or search for node patterns
|
131
149
|
def run!
|
150
|
+
raise 'pry and parallel options are incompatible :(' if @parallel && @pry
|
151
|
+
|
132
152
|
if @help || @files.empty? && @pattern.nil?
|
133
153
|
puts option_parser.help
|
134
154
|
else
|
@@ -137,6 +157,7 @@ module Fast
|
|
137
157
|
end
|
138
158
|
|
139
159
|
# Create fast expression from node pattern using the command line
|
160
|
+
# @return [Array<Fast::Find>] with the expression from string.
|
140
161
|
def expression
|
141
162
|
Fast.expression(@pattern)
|
142
163
|
end
|
@@ -146,24 +167,29 @@ module Fast
|
|
146
167
|
# If capture option is enabled it will only print the captures, otherwise it
|
147
168
|
# prints all the results.
|
148
169
|
def search
|
149
|
-
if debug_mode?
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
report(result, file)
|
156
|
-
end
|
170
|
+
return Fast.debug(&method(:execute_search)) if debug_mode?
|
171
|
+
|
172
|
+
execute_search do |file, results|
|
173
|
+
results.each do |result|
|
174
|
+
binding.pry if @pry # rubocop:disable Lint/Debugger
|
175
|
+
report(file, result)
|
157
176
|
end
|
158
177
|
end
|
159
178
|
end
|
160
179
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
180
|
+
# Executes search for all files yielding the results
|
181
|
+
# @yieldparam [String, Array] with file and respective search results
|
182
|
+
def execute_search(&on_result)
|
183
|
+
Fast.public_send(search_method_name,
|
184
|
+
expression,
|
185
|
+
@files,
|
186
|
+
parallel: parallel?,
|
187
|
+
on_result: on_result)
|
188
|
+
end
|
189
|
+
|
190
|
+
# @return [Symbol] with `:capture_all` or `:search_all` depending the command line options
|
191
|
+
def search_method_name
|
192
|
+
@captures ? :capture_all : :search_all
|
167
193
|
end
|
168
194
|
|
169
195
|
# @return [Boolean] true when "-d" or "--debug" option is passed
|
@@ -176,10 +202,20 @@ module Fast
|
|
176
202
|
puts(info) if debug_mode?
|
177
203
|
end
|
178
204
|
|
205
|
+
def parallel?
|
206
|
+
@parallel == true
|
207
|
+
end
|
208
|
+
|
179
209
|
# Report results using the actual options binded from command line.
|
180
210
|
# @see Fast.report
|
181
|
-
def report(
|
182
|
-
Fast.report(result,
|
211
|
+
def report(file, result)
|
212
|
+
Fast.report(result,
|
213
|
+
file: file,
|
214
|
+
show_link: @show_link,
|
215
|
+
show_sexp: @show_sexp,
|
216
|
+
headless: @headless,
|
217
|
+
bodyless: @bodyless,
|
218
|
+
colorize: @colorize)
|
183
219
|
end
|
184
220
|
|
185
221
|
# Find shortcut by name. Preloads all `Fastfiles` before start.
|
@@ -190,7 +226,6 @@ module Fast
|
|
190
226
|
Fast.load_fast_files!
|
191
227
|
|
192
228
|
shortcut = Fast.shortcuts[name] || Fast.shortcuts[name.to_sym]
|
193
|
-
|
194
229
|
shortcut || exit_shortcut_not_found(name)
|
195
230
|
end
|
196
231
|
|
@@ -198,7 +233,10 @@ module Fast
|
|
198
233
|
# Prints available shortcuts as extra help and exit with code 1.
|
199
234
|
def exit_shortcut_not_found(name)
|
200
235
|
puts "Shortcut \033[1m#{name}\033[0m not found :("
|
201
|
-
|
236
|
+
if Fast.shortcuts.any?
|
237
|
+
puts "Available shortcuts are: #{Fast.shortcuts.keys.join(', ')}."
|
238
|
+
Fast.load_fast_files!
|
239
|
+
end
|
202
240
|
exit 1
|
203
241
|
end
|
204
242
|
end
|
data/lib/fast/experiment.rb
CHANGED
@@ -290,7 +290,7 @@ module Fast
|
|
290
290
|
Fast.search(experiment.expression, @ast) || []
|
291
291
|
end
|
292
292
|
|
293
|
-
# rubocop:disable Metrics/
|
293
|
+
# rubocop:disable Metrics/MethodLength
|
294
294
|
#
|
295
295
|
# Execute partial replacements generating new file with the
|
296
296
|
# content replaced.
|
@@ -312,7 +312,6 @@ module Fast
|
|
312
312
|
new_content
|
313
313
|
end
|
314
314
|
|
315
|
-
# rubocop:enable Metrics/AbcSize
|
316
315
|
# rubocop:enable Metrics/MethodLength
|
317
316
|
|
318
317
|
# Write new file name depending on the combination
|
data/lib/fast/git.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Git plugin for Fast::Node.
|
4
|
+
# It allows to easily access metadata from current file.
|
5
|
+
module Fast
|
6
|
+
# This is not required by default, so to use it, you should require it first.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# require 'fast/git'
|
10
|
+
# Fast.ast_from_file('lib/fast.rb').git_log.first.author.name # => "Jonatas Davi Paganini"
|
11
|
+
class Node < Astrolabe::Node
|
12
|
+
# @return [Git::Base] from current directory
|
13
|
+
def git
|
14
|
+
require 'git' unless defined? Git
|
15
|
+
Git.open('.')
|
16
|
+
end
|
17
|
+
|
18
|
+
# @return [Git::Object::Blob] from current #buffer_name
|
19
|
+
def git_blob
|
20
|
+
return unless from_file?
|
21
|
+
|
22
|
+
git.gblob(buffer_name)
|
23
|
+
end
|
24
|
+
|
25
|
+
# @return [Git::Log] from the current #git_blob
|
26
|
+
# buffer-name
|
27
|
+
def git_log
|
28
|
+
git_blob.log
|
29
|
+
end
|
30
|
+
|
31
|
+
# @return [Git::Object::Commit]
|
32
|
+
def last_commit
|
33
|
+
git_log.first
|
34
|
+
end
|
35
|
+
|
36
|
+
# @return [String] with last commit SHA
|
37
|
+
def sha
|
38
|
+
last_commit.sha
|
39
|
+
end
|
40
|
+
|
41
|
+
# @return [String] with remote URL
|
42
|
+
def remote_url
|
43
|
+
git.remote.url
|
44
|
+
end
|
45
|
+
|
46
|
+
# Given #remote_url is "git@github.com:namespace/project.git"
|
47
|
+
# Or #remote_url is "https://github.com/namespace/project.git"
|
48
|
+
# @return [String] "https://github.com/namespace/project"
|
49
|
+
def project_url
|
50
|
+
return remote_url.gsub(/\.git$/, '') if remote_url.start_with?('https')
|
51
|
+
|
52
|
+
remote_url
|
53
|
+
.gsub('git@', 'https://')
|
54
|
+
.gsub(/:(\w)/, '/\\1')
|
55
|
+
.gsub(/\.git$/, '')
|
56
|
+
end
|
57
|
+
|
58
|
+
def file
|
59
|
+
buffer_name.gsub("#{Dir.pwd}/", '')
|
60
|
+
end
|
61
|
+
|
62
|
+
# @return
|
63
|
+
def line_range
|
64
|
+
lines.map { |l| "L#{l}" }.join('-')
|
65
|
+
end
|
66
|
+
|
67
|
+
# @return [Array] with lines range
|
68
|
+
def lines
|
69
|
+
exp = loc.expression
|
70
|
+
first_line = exp.first_line
|
71
|
+
last_line = exp.last_line
|
72
|
+
[first_line, last_line].uniq
|
73
|
+
end
|
74
|
+
|
75
|
+
# @return [Integer] lines of code from current block
|
76
|
+
def lines_of_code
|
77
|
+
lines.last - lines.first + 1
|
78
|
+
end
|
79
|
+
|
80
|
+
# @return [String] a markdown link with #md_link_description and #link
|
81
|
+
def md_link(text = md_link_description)
|
82
|
+
"[#{text}](#{link})"
|
83
|
+
end
|
84
|
+
|
85
|
+
# @return [String] with the source cutting arguments from method calls to be
|
86
|
+
# able to create a markdown link without parens.
|
87
|
+
def md_link_description
|
88
|
+
source[/([^\r\(]+)\(/, 1] || source
|
89
|
+
end
|
90
|
+
|
91
|
+
# @return [String] with formatted repositorym link
|
92
|
+
def link
|
93
|
+
"#{project_url}/blob/master/#{buffer_name}##{line_range}"
|
94
|
+
end
|
95
|
+
|
96
|
+
# @return [String] with permanent link to the actual commit
|
97
|
+
def permalink
|
98
|
+
"#{project_url}/blob/#{sha}/#{buffer_name}##{line_range}"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
data/lib/fast/shortcut.rb
CHANGED
@@ -54,19 +54,16 @@ module Fast
|
|
54
54
|
@block && @args.nil?
|
55
55
|
end
|
56
56
|
|
57
|
-
def options
|
58
|
-
@args.select { |arg| arg.start_with? '-' }
|
59
|
-
end
|
60
|
-
|
61
|
-
def params
|
62
|
-
@args - options
|
63
|
-
end
|
64
|
-
|
65
57
|
# Merge extra arguments from input returning a new arguments array keeping
|
66
58
|
# the options from previous alias and replacing the files with the
|
67
59
|
# @param [Array] extra_args
|
68
60
|
def merge_args(extra_args)
|
69
|
-
|
61
|
+
all_args = (@args + extra_args).uniq
|
62
|
+
options = all_args.select { |arg| arg.start_with? '-' }
|
63
|
+
files = extra_args.select(&File.method(:exists?))
|
64
|
+
command = (@args - options - files).first
|
65
|
+
|
66
|
+
[command, *options, *files]
|
70
67
|
end
|
71
68
|
|
72
69
|
# 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,10 @@ 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
|
+
- Research: research.md
|
26
|
+
- Ideas: ideas.md
|
27
|
+
- 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.
|
4
|
+
version: 0.2.0
|
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:
|
11
|
+
date: 2020-09-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: astrolabe
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: parallel
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: parser
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -122,20 +122,48 @@ dependencies:
|
|
122
122
|
- - ">="
|
123
123
|
- !ruby/object:Gem::Version
|
124
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: pry
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: git
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - ">="
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
125
153
|
- !ruby/object:Gem::Dependency
|
126
154
|
name: rake
|
127
155
|
requirement: !ruby/object:Gem::Requirement
|
128
156
|
requirements:
|
129
|
-
- - "
|
157
|
+
- - ">="
|
130
158
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
159
|
+
version: '0'
|
132
160
|
type: :development
|
133
161
|
prerelease: false
|
134
162
|
version_requirements: !ruby/object:Gem::Requirement
|
135
163
|
requirements:
|
136
|
-
- - "
|
164
|
+
- - ">="
|
137
165
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
166
|
+
version: '0'
|
139
167
|
- !ruby/object:Gem::Dependency
|
140
168
|
name: rspec
|
141
169
|
requirement: !ruby/object:Gem::Requirement
|
@@ -210,16 +238,22 @@ dependencies:
|
|
210
238
|
name: simplecov
|
211
239
|
requirement: !ruby/object:Gem::Requirement
|
212
240
|
requirements:
|
213
|
-
- - "
|
241
|
+
- - "~>"
|
214
242
|
- !ruby/object:Gem::Version
|
215
|
-
version: '0'
|
243
|
+
version: '0.10'
|
244
|
+
- - "<"
|
245
|
+
- !ruby/object:Gem::Version
|
246
|
+
version: '0.18'
|
216
247
|
type: :development
|
217
248
|
prerelease: false
|
218
249
|
version_requirements: !ruby/object:Gem::Requirement
|
219
250
|
requirements:
|
220
|
-
- - "
|
251
|
+
- - "~>"
|
221
252
|
- !ruby/object:Gem::Version
|
222
|
-
version: '0'
|
253
|
+
version: '0.10'
|
254
|
+
- - "<"
|
255
|
+
- !ruby/object:Gem::Version
|
256
|
+
version: '0.18'
|
223
257
|
description: Allow you to search for code using node pattern syntax.
|
224
258
|
email:
|
225
259
|
- jonatasdp@gmail.com
|
@@ -233,6 +267,7 @@ files:
|
|
233
267
|
- ".projections.json"
|
234
268
|
- ".rspec"
|
235
269
|
- ".rubocop.yml"
|
270
|
+
- ".sourcelevel.yml"
|
236
271
|
- ".travis.yml"
|
237
272
|
- CODE_OF_CONDUCT.md
|
238
273
|
- Fastfile
|
@@ -247,11 +282,16 @@ files:
|
|
247
282
|
- bin/fast-experiment
|
248
283
|
- bin/setup
|
249
284
|
- docs/command_line.md
|
285
|
+
- docs/editors-integration.md
|
250
286
|
- docs/experiments.md
|
287
|
+
- docs/ideas.md
|
251
288
|
- docs/index.md
|
252
289
|
- docs/pry-integration.md
|
290
|
+
- docs/research.md
|
291
|
+
- docs/shortcuts.md
|
253
292
|
- docs/similarity_tutorial.md
|
254
293
|
- docs/syntax.md
|
294
|
+
- docs/videos.md
|
255
295
|
- examples/build_stubbed_and_let_it_be_experiment.rb
|
256
296
|
- examples/experimental_replacement.rb
|
257
297
|
- examples/find_usage.rb
|
@@ -267,6 +307,7 @@ files:
|
|
267
307
|
- lib/fast.rb
|
268
308
|
- lib/fast/cli.rb
|
269
309
|
- lib/fast/experiment.rb
|
310
|
+
- lib/fast/git.rb
|
270
311
|
- lib/fast/rewriter.rb
|
271
312
|
- lib/fast/shortcut.rb
|
272
313
|
- lib/fast/version.rb
|
@@ -284,7 +325,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
284
325
|
requirements:
|
285
326
|
- - ">="
|
286
327
|
- !ruby/object:Gem::Version
|
287
|
-
version: '2.
|
328
|
+
version: '2.6'
|
288
329
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
289
330
|
requirements:
|
290
331
|
- - ">="
|