lab42_speculate 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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: []