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 +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: []
         |