lab42_speculate 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/speculate +6 -0
- data/lib/speculate.rb +57 -0
- data/lib/speculate/args.rb +76 -0
- data/lib/speculate/dirs.rb +36 -0
- data/lib/speculate/generator.rb +29 -0
- data/lib/speculate/parser.rb +61 -0
- data/lib/speculate/spec_pair.rb +26 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b3427d6436310d4254e6b44eab9bf4bb987e7baf944c30844e6c5ba3d321f4f5
|
4
|
+
data.tar.gz: b470196d41cc3f1ce0a842c4432ab413f961db0c2f947597beb2517cb179ee54
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 151f993021994a91eb565ea2bedf2d56ccded40629fbb1211ab2ac69b522a5dff72255f1a8aa6a1ce9049abb3a63c5ccb457c728f8a89022d55fa8e86d9e09f5
|
7
|
+
data.tar.gz: f0c0c60a70a94de2ae905b638192b10a04bde6f5890acd4303fff66a3c50f3f0bceecabf129be71ae58bd3a6dc0eccfe570b3e0e953a02a25f71182003deacc4
|
data/bin/speculate
ADDED
data/lib/speculate.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Speculate extend self
|
2
|
+
require_relative 'speculate/args'
|
3
|
+
require_relative 'speculate/dirs'
|
4
|
+
require_relative 'speculate/generator'
|
5
|
+
|
6
|
+
BASE_DIR = 'spec/speculations'
|
7
|
+
|
8
|
+
attr_reader :args
|
9
|
+
|
10
|
+
def base_dir
|
11
|
+
@__base_dir__ ||= args.fetch!(:dest, BASE_DIR)
|
12
|
+
end
|
13
|
+
|
14
|
+
def speculations
|
15
|
+
@__speculations__ ||= _speculations
|
16
|
+
end
|
17
|
+
|
18
|
+
def speculations_dir
|
19
|
+
@__speculations_dir__ ||= args.fetch!(:dir, 'spec/speculations')
|
20
|
+
end
|
21
|
+
|
22
|
+
def speculations_glob
|
23
|
+
@__speculations_glob__ ||= args.fetch!(:glob, '**/*.md')
|
24
|
+
end
|
25
|
+
|
26
|
+
def run args
|
27
|
+
@args = Args.new args
|
28
|
+
if @args.flag!(:force)
|
29
|
+
_force speculations
|
30
|
+
end
|
31
|
+
speculations
|
32
|
+
.filter(&:outdated?)
|
33
|
+
.each(&Generator.method(:generate))
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def _force speculations
|
40
|
+
speculations.each do |speculation|
|
41
|
+
puts "touching #{speculation.speculation.path} as :force was passed in"
|
42
|
+
FileUtils.touch speculation.speculation
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def _speculations
|
47
|
+
speculations = Dir.glob(File.join(speculations_dir, speculations_glob))
|
48
|
+
if speculations.any?
|
49
|
+
puts "Speculations found: #{speculations}"
|
50
|
+
else
|
51
|
+
puts "No Speculations found!!!! :O :O :O"
|
52
|
+
return []
|
53
|
+
end
|
54
|
+
speculations.map{ |speculation| Dirs.speculation_to_dir(speculation, base_dir) }
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
class Speculate::Args
|
2
|
+
|
3
|
+
FLAG_RGX = %r{\A:}
|
4
|
+
KEYWORD_RGX = %r{:\z}
|
5
|
+
|
6
|
+
attr_reader :args
|
7
|
+
|
8
|
+
def empty?; args.empty? end
|
9
|
+
|
10
|
+
def fetch symbol, default=nil, &block
|
11
|
+
index = args.index("#{symbol}:")
|
12
|
+
return default unless index
|
13
|
+
args.fetch( index.succ, default ).tap do |value|
|
14
|
+
return block.(value) if block
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch! symbol, default=nil, &block
|
19
|
+
index = args.index("#{symbol}:")
|
20
|
+
return default unless index
|
21
|
+
args.delete_at index
|
22
|
+
args.fetch( index ) {
|
23
|
+
return default
|
24
|
+
}.tap{ |value|
|
25
|
+
args.delete_at index
|
26
|
+
return block.(value) if block
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
def flag? value
|
31
|
+
args.index ":#{value}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def flag! value
|
35
|
+
flag?(value).tap do |idx|
|
36
|
+
return unless idx
|
37
|
+
args.delete_at(idx)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def positionals
|
42
|
+
args.inject [false, []] do |(last_was_keyword, result), ele|
|
43
|
+
if last_was_keyword
|
44
|
+
[false, result]
|
45
|
+
else
|
46
|
+
case ele
|
47
|
+
when KEYWORD_RGX
|
48
|
+
[true, result]
|
49
|
+
when FLAG_RGX
|
50
|
+
[false, result]
|
51
|
+
else
|
52
|
+
[false, result << ele]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end.last
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_a
|
59
|
+
args.dup
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def initialize with
|
66
|
+
@args = with.dup
|
67
|
+
end
|
68
|
+
|
69
|
+
def _flag arg
|
70
|
+
FLAG_RGX.match? arg
|
71
|
+
end
|
72
|
+
|
73
|
+
def _keyword? arg
|
74
|
+
KEYWORD_RGX.match arg
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
require_relative './spec_pair'
|
4
|
+
module Speculate::Dirs extend self
|
5
|
+
Error = Class.new RuntimeError
|
6
|
+
|
7
|
+
DEFAULT_BASENAME = "__default"
|
8
|
+
SPECULATION_RGX = %r{\ASPECULATE[-_]*(.*)\.md\z}
|
9
|
+
|
10
|
+
attr_reader :base_dir
|
11
|
+
|
12
|
+
def speculation_to_dir speculation_file, base_dir
|
13
|
+
@base_dir = base_dir
|
14
|
+
|
15
|
+
_assure_dir
|
16
|
+
speculation_file, spec_path = _assure_speculation speculation_file
|
17
|
+
|
18
|
+
Speculate::SpecPair.new speculation_file, spec_path
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def _assure_dir
|
25
|
+
FileUtils.mkdir_p(base_dir)
|
26
|
+
end
|
27
|
+
|
28
|
+
def _assure_speculation speculation_file
|
29
|
+
|
30
|
+
basename = File.basename(speculation_file).sub(%r{\..*\z}i, "").downcase
|
31
|
+
specname = File.join(base_dir, "#{basename}_spec.rb")
|
32
|
+
|
33
|
+
[speculation_file, specname]
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative './parser.rb'
|
2
|
+
module Speculate::Generator extend self
|
3
|
+
Error = Class.new RuntimeError
|
4
|
+
|
5
|
+
def generate pair
|
6
|
+
unless pair.outdated?
|
7
|
+
raise Error,
|
8
|
+
"Must not call generate for #{pair.speculation.path} -> #{pair.spec.path}, because it is not outdated"
|
9
|
+
end
|
10
|
+
puts "Generating: #{pair.speculation.path} -> #{pair.spec.path}"
|
11
|
+
text = Speculate::Parser.new(pair.speculation).parse
|
12
|
+
File.open(pair.spec.path, "w"){ |f|
|
13
|
+
f.puts _header(pair.speculation.path)
|
14
|
+
f.puts text
|
15
|
+
f.puts _footer
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def _footer
|
23
|
+
%{end}
|
24
|
+
end
|
25
|
+
|
26
|
+
def _header name
|
27
|
+
%{RSpec.describe #{name.inspect} do}
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
class Speculate::Parser
|
2
|
+
Error = Class.new RuntimeError
|
3
|
+
|
4
|
+
SPECULATION_END_RGX = %r{\A\s{0,3}(?:```)|(?:~~~)\s*\z}
|
5
|
+
SPECULATION_START_RGX = %r{\A\s{0,3}(?:```)|(?:~~~)(\w+)speculate}
|
6
|
+
|
7
|
+
attr_reader :state, :stream
|
8
|
+
|
9
|
+
def parse
|
10
|
+
@state = :outer
|
11
|
+
_parse
|
12
|
+
lines
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def initialize speculation
|
19
|
+
@stream =
|
20
|
+
speculation
|
21
|
+
.each_line(chomp: true)
|
22
|
+
.lazy
|
23
|
+
end
|
24
|
+
|
25
|
+
|
26
|
+
# Memos
|
27
|
+
# =====
|
28
|
+
def lines
|
29
|
+
@__lines__ ||= []
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# Parser
|
34
|
+
# ======
|
35
|
+
def _parse
|
36
|
+
stream.each do |line|
|
37
|
+
case state
|
38
|
+
when :outer
|
39
|
+
_parse_outer line
|
40
|
+
when :inner
|
41
|
+
_parse_inner line
|
42
|
+
else
|
43
|
+
raise Error, "illegal state #{state}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def _parse_inner line
|
49
|
+
if SPECULATION_END_RGX =~ line
|
50
|
+
@state = :outer
|
51
|
+
else
|
52
|
+
lines << line
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def _parse_outer line
|
57
|
+
if SPECULATION_START_RGX =~ line
|
58
|
+
@state = :inner
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
class Speculate::SpecPair
|
3
|
+
|
4
|
+
attr_reader :spec, :speculation
|
5
|
+
|
6
|
+
def outdated?
|
7
|
+
speculation.mtime >= spec.mtime
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def initialize speculation_name, spec_path
|
14
|
+
@speculation = File.new speculation_name
|
15
|
+
|
16
|
+
FileUtils.touch(spec_path, mtime: speculation.mtime - 1) unless File.exists? spec_path
|
17
|
+
@spec = File.new spec_path
|
18
|
+
end
|
19
|
+
|
20
|
+
def _spec_pair basename
|
21
|
+
specname = File.join(base_dir, "#{basename}_spec.rb")
|
22
|
+
FileUtils.touch(specname, mtime: speculation.mtime - 1) unless File.exists? specname
|
23
|
+
OpenStruct.new(speculation: speculation, spec: File.new(specname))
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lab42_speculate
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.3
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Robert Dober
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-01-26 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rspec
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.9'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.9'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry-byebug
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.7'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.7'
|
41
|
+
description: Extract RSpecs from Markdown
|
42
|
+
email: robert.dober@gmail.com
|
43
|
+
executables:
|
44
|
+
- speculate
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- bin/speculate
|
49
|
+
- lib/speculate.rb
|
50
|
+
- lib/speculate/args.rb
|
51
|
+
- lib/speculate/dirs.rb
|
52
|
+
- lib/speculate/generator.rb
|
53
|
+
- lib/speculate/parser.rb
|
54
|
+
- lib/speculate/spec_pair.rb
|
55
|
+
homepage: https://github.com/robertdober/speculate
|
56
|
+
licenses:
|
57
|
+
- Apache-2.0
|
58
|
+
metadata: {}
|
59
|
+
post_install_message:
|
60
|
+
rdoc_options: []
|
61
|
+
require_paths:
|
62
|
+
- lib
|
63
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: 2.7.0
|
68
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubygems_version: 3.1.2
|
75
|
+
signing_key:
|
76
|
+
specification_version: 4
|
77
|
+
summary: Extract RSpecs from Markdown
|
78
|
+
test_files: []
|