speculate_about 0.1.2 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d6c603b51bd04471204c4584fb1697f5a27dd7b578abd012c805046e7d9a49dc
4
- data.tar.gz: 82f31cc63352e6d3c380b860a40a1f84a2f133b7b4f8a391363176f57d808415
3
+ metadata.gz: d53e888a2cad71c7c20205f0f34d7ededa3df3feceef7d567f051d362a36ccb8
4
+ data.tar.gz: ee00700ca0a19000b8098cb3022b462da0537477d58ee912f250aba6b02e3e7c
5
5
  SHA512:
6
- metadata.gz: bd30e3a46232a0d38b0d0725aa89df98f7d724faef50e350e3bacf106c552e279569087b830f93a656015dca03f5fe1e0ff0c511484a2c12ac3331ebb8e5c51a
7
- data.tar.gz: f48a6400a5bd1d6971780e5c8261d957b64af79c96baa544dd21b4050240343da77bc48141b4d0097da32ee4ee4ff5d065c7d3aa0df65584a71caf99b4724d09
6
+ metadata.gz: 3ced515885a50ff873cc4b471fe03eab69dc3e7c4f409e4e5ff392a91bfd94a08946aae7eb866607b27ecad62104beee68d8a52230fa2e216e1a544800a4ef0e
7
+ data.tar.gz: 792619744dab6387ad2e70c7fa53eb49c3b8b9f26470a5de7c92477c3cc274075d7cff720b5fb8dc0a87bf71d2af016517e72449d56298824d3f865253b64192
@@ -3,24 +3,40 @@ require 'rspec'
3
3
  require 'speculations/parser'
4
4
 
5
5
  module SpeculateAbout
6
- def speculate_about file
7
- path = _find_file(file, File.dirname( caller.first ))
8
- code = _compile path, file
9
- ENV["SPECULATE_ABOUT_DEBUG"] ? puts(code) : instance_eval(code)
6
+ def speculate_about file, alternate_syntax: false
7
+ paths = _find_files(file, File.dirname( caller.first ))
8
+ raise ArgumentError, "no files found for pattern #{file}" if paths.empty?
9
+ paths.each do |path|
10
+ code = _compile path, _readable(path), alternate_syntax: alternate_syntax
11
+ ENV["SPECULATE_ABOUT_DEBUG"] ? _show(code, path) : instance_eval(code, path)
12
+ end
10
13
  end
11
14
 
12
15
 
13
16
  private
14
17
 
15
- def _compile path, file
16
- ast = Speculations::Parser.new.parse_from_file(path, file)
18
+ def _compile path, file, alternate_syntax: false
19
+ ast = Speculations::Parser.new.parse_from_file(path, file, alternate_syntax: alternate_syntax)
17
20
  ast.to_code
18
21
  end
19
- def _find_file file, local_path
20
- return file if File.readable? file
21
- local_file = File.join(local_path, file)
22
- return local_file if File.readable? local_file
23
- raise ArgumentError, "file #{file.inspect} not found"
22
+ def _readable(path)
23
+ d = File.dirname(path)
24
+ File.join(File.basename(d), File.basename(path))
25
+ end
26
+ def _find_files file, local_path
27
+ [Dir.pwd, local_path]
28
+ .flat_map do |dir|
29
+ Dir.glob(File.join(dir, file))
30
+ end
31
+ end
32
+ def _show(code, path)
33
+ message = "Generated code for #{path}"
34
+ _underline(message)
35
+ puts code
36
+ end
37
+ def _underline(message, ul: "=")
38
+ puts message
39
+ puts message.gsub(/./, ul)
24
40
  end
25
41
  end
26
42
 
@@ -3,7 +3,7 @@ class Speculations::Parser
3
3
  require_relative './parser/context'
4
4
  require_relative './parser/state'
5
5
 
6
- attr_reader :filename, :input, :orig_filename, :root, :state
6
+ attr_reader :alternate_syntax, :filename, :input, :orig_filename, :root, :state
7
7
 
8
8
  def self.parsers
9
9
  @__parsers__ ||= {
@@ -14,7 +14,8 @@ class Speculations::Parser
14
14
  }
15
15
  end
16
16
 
17
- def parse_from_file file, orig_filename = nil
17
+ def parse_from_file file, orig_filename = nil, alternate_syntax: false
18
+ @alternate_syntax = alternate_syntax
18
19
  @filename = file
19
20
  @orig_filename = orig_filename || file
20
21
  @input = File
@@ -31,7 +32,7 @@ class Speculations::Parser
31
32
  end
32
33
 
33
34
  def parse!
34
- root = node = Context.new(name: "Speculations from #{@filename}", lnb: 0, filename: @filename, orig_filename: orig_filename, parent: nil)
35
+ root = node = Context.new(alternate_syntax: alternate_syntax, name: "Speculations from #{@filename}", lnb: 0, filename: @filename, orig_filename: orig_filename, parent: nil)
35
36
  input.each_with_index do |line, lnb|
36
37
  @state, node = self.class.parsers.fetch(@state).parse(line, lnb.succ, node)
37
38
  end
@@ -3,16 +3,17 @@ class Speculations::Parser::Context
3
3
  require_relative './context/example'
4
4
  require_relative './context/setup'
5
5
 
6
- attr_reader :filename, :level, :lnb, :name, :orig_filename, :parent, :setup
6
+ attr_reader :alternate_syntax, :filename, :level, :lnb, :name, :orig_filename, :parent, :potential_name, :setup
7
7
 
8
8
  def add_child(name:, lnb:)
9
9
  raise "Illegal nesting" if parent
10
- children << self.class.new(name: name, lnb: lnb, parent: self)
10
+ children << self.class.new(alternate_syntax: alternate_syntax, name: name, lnb: lnb, parent: self)
11
11
  children.last
12
12
  end
13
13
 
14
14
  def add_example(lnb:, line:)
15
- examples << Example.new(lnb: lnb, parent: self, line: line)
15
+ examples << Example.new(lnb: lnb, parent: self, line: line, name: potential_name)
16
+ @potential_name = nil
16
17
  examples.last
17
18
  end
18
19
 
@@ -38,6 +39,10 @@ class Speculations::Parser::Context
38
39
  lines.flatten.map{ |line| "#{prefix}#{line.strip}" }.join("\n")
39
40
  end
40
41
 
42
+ def set_name(potential_name)
43
+ @potential_name = potential_name
44
+ end
45
+
41
46
  def set_setup(lnb:)
42
47
  @setup = Setup.new(lnb: lnb, parent: self)
43
48
  end
@@ -55,8 +60,9 @@ class Speculations::Parser::Context
55
60
 
56
61
  private
57
62
 
58
- def initialize(lnb:, name:, filename: nil, orig_filename: nil, parent: nil)
63
+ def initialize(alternate_syntax: false, lnb:, name:, filename: nil, orig_filename: nil, parent: nil)
59
64
  _init_from_parent filename, orig_filename, parent
65
+ @alternate_syntax = alternate_syntax
60
66
  @level = parent ? parent.level.succ : 1
61
67
  @lnb = lnb
62
68
  @setup = nil
@@ -69,8 +75,12 @@ class Speculations::Parser::Context
69
75
  end
70
76
 
71
77
  def _init_from_parent filename, orig_filename, parent
72
- @filename = parent ? parent.filename : filename
78
+ _set_filename filename, orig_filename, parent
73
79
  @orig_filename = parent ? parent.orig_filename : orig_filename
80
+ end
81
+
82
+ def _set_filename filename, orig_filename, parent
83
+ @filename = parent ? parent.filename : filename
74
84
  raise ArgumentError, "no filename given in root context" unless @filename
75
85
  end
76
86
 
@@ -24,16 +24,18 @@ class Speculations::Parser::Context::Example
24
24
 
25
25
  private
26
26
 
27
- def initialize(lnb:, line:, parent:)
27
+ def initialize(lnb:, line:, parent:, name: nil)
28
28
  @lnb = lnb
29
29
  @parent = parent
30
- @name = _compute_name(lnb: lnb, line: line, parent: parent)
30
+ @name = _compute_name(lnb: lnb, line: line, parent: parent, name: name)
31
31
  end
32
32
 
33
- def _compute_name(lnb:, parent:, line:)
34
- _, name = NAMED_EXAMPLE.match(line).to_a
33
+ def _compute_name(lnb:, parent:, line:, name:)
34
+ _, name1 = NAMED_EXAMPLE.match(line).to_a
35
35
 
36
- if name&.empty? == false # SIC
36
+ if name1&.empty? == false # SIC
37
+ "#{name1} (#{parent.orig_filename}:#{lnb.succ})"
38
+ elsif name
37
39
  "#{name} (#{parent.orig_filename}:#{lnb.succ})"
38
40
  else
39
41
  "Example from #{parent.orig_filename}:#{lnb.succ}"
@@ -9,6 +9,9 @@ module Speculations::Parser::State extend self
9
9
  EOBLOCK_RGX = %r[\A\s{0,3}```\s*\z]
10
10
  EXAMPLE_RGX = %r[\A\s{0,3}```.*\s:example]
11
11
  INCLUDE_RGX = %r[\A\s{0,3}```.*\s:include]
12
+ NAME_RGX = %r[\A\s{0,3}Example:?\s+(.*)]i
13
+ RUBY_RGX = %r[\A\s{0,3}```ruby]
14
+ WS_RGX = %r[\A\s*\z]
12
15
 
13
16
  def before_match line
14
17
  BEFORE_RGX =~ line
@@ -31,4 +34,16 @@ module Speculations::Parser::State extend self
31
34
  def include_match line
32
35
  INCLUDE_RGX =~ line
33
36
  end
37
+
38
+ def potential_name line
39
+ NAME_RGX.match(line)
40
+ end
41
+
42
+ def ruby_match line
43
+ RUBY_RGX =~ line
44
+ end
45
+
46
+ def ws_match line
47
+ WS_RGX =~ line
48
+ end
34
49
  end
@@ -4,6 +4,42 @@ module Speculations
4
4
  module Out extend self
5
5
 
6
6
  def parse line, lnb, node
7
+ if node.alternate_syntax
8
+ _parse_alternate line, lnb, node
9
+ else
10
+ _parse_classical line, lnb, node
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def _parse_alternate line, lnb, node
17
+ case
18
+ when name = State.context_match(line)
19
+ node = node.parent if node.parent
20
+ new_node = node.add_child(name: name, lnb: lnb)
21
+ new_node.set_name(nil)
22
+ [:out, new_node]
23
+ when State.ws_match(line)
24
+ [:out, node]
25
+ when name = State.potential_name(line)
26
+ node.set_name(name[1])
27
+ [:out, node]
28
+ when State.ruby_match(line)
29
+ if node.potential_name
30
+ node = node.add_example(lnb: lnb, line: line)
31
+ [:exa, node]
32
+ else
33
+ node = node.add_include(lnb: lnb)
34
+ [:inc, node]
35
+ end
36
+ else
37
+ node.set_name(nil)
38
+ [:out, node]
39
+ end
40
+ end
41
+
42
+ def _parse_classical line, lnb, node
7
43
  case
8
44
  when name = State.context_match(line)
9
45
  node = node.parent if node.parent
@@ -18,6 +54,9 @@ module Speculations
18
54
  when State.include_match(line)
19
55
  node = node.add_include(lnb: lnb)
20
56
  [:inc, node]
57
+ when name = State.potential_name(line)
58
+ node.set_name(name[1])
59
+ [:out, node]
21
60
  else
22
61
  [:out, node]
23
62
  end
@@ -0,0 +1,3 @@
1
+ module SpeculateAbout
2
+ VERSION = "0.3.0"
3
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: speculate_about
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robert Dober
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-18 00:00:00.000000000 Z
11
+ date: 2020-11-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -24,7 +24,7 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '3.9'
27
- description: Allows Markdown or other text files to be used as literal specs, a la
27
+ description: Allows Markdown or other text files to be used as literal specs, à la
28
28
  Elixr doctest, but from any file.
29
29
  email: robert.dober@gmail.com
30
30
  executables: []
@@ -43,11 +43,12 @@ files:
43
43
  - lib/speculations/parser/state/exa.rb
44
44
  - lib/speculations/parser/state/inc.rb
45
45
  - lib/speculations/parser/state/out.rb
46
+ - lib/speculations/version.rb
46
47
  homepage: https://github.com/robertdober/speculate
47
48
  licenses:
48
49
  - Apache-2.0
49
50
  metadata: {}
50
- post_install_message:
51
+ post_install_message:
51
52
  rdoc_options: []
52
53
  require_paths:
53
54
  - lib
@@ -63,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
64
  version: '0'
64
65
  requirements: []
65
66
  rubygems_version: 3.1.2
66
- signing_key:
67
+ signing_key:
67
68
  specification_version: 4
68
69
  summary: Extract RSpecs from Markdown
69
70
  test_files: []