lab42_speculate 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'fileutils'
4
+ require_relative '../lib/speculate.rb'
5
+
6
+ Speculate.run ARGV
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: []