lab42_literate 0.1.2 → 0.1.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 +4 -4
- data/README.md +77 -5
- data/lib/lab42/literate.rb +8 -0
- data/lib/lab42/literate/extractor/block.rb +16 -0
- data/lib/lab42/literate/group_doctest.rb +13 -6
- data/lib/lab42/literate/version.rb +1 -1
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5dc4434c53fc4b7ae709911bed4ea867eee642b4
|
4
|
+
data.tar.gz: 3a68fe614d6f32e3b5e13d8bb46a02ca28347ffc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d9e5a3cab528ecc1e3c8b4aec44068506e69dfc0445e121ddaef0e6fb350b8c379e6ec1141f48222cb775d7a66925d988d6e65cc23e9b7c21358066a0ddc5184
|
7
|
+
data.tar.gz: 128ced3230f2486533283039ed0ae96d1c278826d4dcc557b5329b52d664ac0f6f4067f75ad3f9dd5e77b547ee64f3982358bb87ecc9c83fbdab4342045ea766
|
data/README.md
CHANGED
@@ -7,7 +7,17 @@
|
|
7
7
|
[](https://codeclimate.com/github/RobertDober/lab42_literate)
|
8
8
|
[](https://codeclimate.com/github/RobertDober/lab42_literate)
|
9
9
|
|
10
|
-
## Literate Programming à la doctest.
|
10
|
+
## Literate Programming à la doctest in Elxir.
|
11
|
+
|
12
|
+
[Elixir Doctest](https://elixir-lang.org/getting-started/mix-otp/docs-tests-and-with.html#doctests) has inspired this gem.
|
13
|
+
|
14
|
+
Of course Elixir doctests from the metadata of a compiled elixir source (beam).
|
15
|
+
|
16
|
+
As in Ruby we do not have any metadata this works with simple text extraction and evalutaion.
|
17
|
+
|
18
|
+
This gives us however the possibility to write our doctests in **any** file and allows you
|
19
|
+
to assure that your `README.md` code examples are **all correct**.
|
20
|
+
|
11
21
|
|
12
22
|
Just extract code blocks from any file, and run them as specs with a simple `doctest file` in an RSpec example group.
|
13
23
|
|
@@ -49,14 +59,76 @@ with
|
|
49
59
|
|
50
60
|
### How does it work?
|
51
61
|
|
52
|
-
Each block ` ```ruby literate` creates an example with title `"literate block in #{file}:#{start_lnb}..#{end_lnb}"
|
53
|
-
|
62
|
+
Each block ` ```ruby literate` creates an example group with title `"literate block in #{file}:#{start_lnb}..#{end_lnb}"`.
|
63
|
+
|
64
|
+
Then an anonymous example `it do ...`
|
65
|
+
and instance_evals the lines from the block in this example's context.
|
54
66
|
|
55
67
|
|
56
68
|
### Setup?
|
57
69
|
|
58
|
-
Not yet.
|
59
70
|
|
60
|
-
|
71
|
+
#### Inside the spec calling `doctest`
|
72
|
+
|
73
|
+
|
74
|
+
Given this literate file
|
75
|
+
|
76
|
+
```ruby literate
|
77
|
+
foo.reverse #=> 'oof'
|
78
|
+
```
|
79
|
+
|
80
|
+
will perfectly work if you setup your spec as follows
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
RSpec.describe 'FOO', type: :literate do
|
84
|
+
let(:foo){ 'foo' }
|
85
|
+
doctest('literate_file.md')
|
86
|
+
end
|
87
|
+
```
|
88
|
+
|
89
|
+
|
90
|
+
#### Inside the literal file itself
|
91
|
+
|
92
|
+
All literate blocks containing a `Given` block inside the document will be
|
93
|
+
executed in the context in which `doctest` has been called, **before** the
|
94
|
+
example blocks will be generated, thusly the following literate file will
|
95
|
+
succeed
|
96
|
+
|
97
|
+
```ruby literate
|
98
|
+
Given do
|
99
|
+
let(:a){ 1 }
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
```ruby literate
|
104
|
+
a + b #=> 42
|
105
|
+
```
|
106
|
+
|
107
|
+
```ruby literate
|
108
|
+
Given do
|
109
|
+
let(:b){ 41 }
|
110
|
+
end
|
111
|
+
```
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
### Explicit Title of the generated Example Group
|
61
116
|
|
62
117
|
Just add text after ` ```ruby literate`
|
118
|
+
|
119
|
+
E.g.
|
120
|
+
|
121
|
+
```ruby literate Assure errors are empty
|
122
|
+
|
123
|
+
...
|
124
|
+
expect(errors).to be_empty
|
125
|
+
|
126
|
+
```
|
127
|
+
|
128
|
+
### Calling `doctest` inside an Example
|
129
|
+
|
130
|
+
Will be deprecated.
|
131
|
+
|
132
|
+
Does not support all features.
|
133
|
+
|
134
|
+
Use at own risk.
|
data/lib/lab42/literate.rb
CHANGED
@@ -2,10 +2,18 @@ module Lab42
|
|
2
2
|
module Literate
|
3
3
|
require_relative 'literate/example_doctest'
|
4
4
|
require_relative 'literate/group_doctest'
|
5
|
+
|
6
|
+
module Given
|
7
|
+
def Given &blk
|
8
|
+
instance_exec(&blk)
|
9
|
+
end
|
10
|
+
end
|
5
11
|
end
|
6
12
|
end
|
7
13
|
|
8
14
|
RSpec.configure do | conf |
|
9
15
|
conf.extend Lab42::Literate::GroupDoctest, type: :literate
|
16
|
+
conf.extend Lab42::Literate::Given, type: :literate
|
17
|
+
|
10
18
|
conf.include Lab42::Literate::ExampleDoctest, type: :literate
|
11
19
|
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
require 'parser/current'
|
2
|
+
Parser::Builders::Default.emit_lambda = true
|
3
|
+
Parser::Builders::Default.emit_procarg0 = true
|
4
|
+
|
1
5
|
class Lab42::Literate::Extractor::Block
|
2
6
|
attr_reader :lines, :start_lnb, :title
|
3
7
|
|
@@ -5,14 +9,23 @@ class Lab42::Literate::Extractor::Block
|
|
5
9
|
lines << line
|
6
10
|
end
|
7
11
|
|
12
|
+
|
8
13
|
def get_title alternative
|
9
14
|
title.empty? ? alternative : title
|
10
15
|
end
|
11
16
|
|
17
|
+
|
18
|
+
def given?
|
19
|
+
parsed.children.first.children == [nil, :Given]
|
20
|
+
rescue
|
21
|
+
false
|
22
|
+
end
|
23
|
+
|
12
24
|
def range
|
13
25
|
start_lnb..(start_lnb.pred + lines.size)
|
14
26
|
end
|
15
27
|
|
28
|
+
|
16
29
|
private
|
17
30
|
|
18
31
|
def initialize start_lnb, title: ''
|
@@ -21,4 +34,7 @@ class Lab42::Literate::Extractor::Block
|
|
21
34
|
@title = title
|
22
35
|
end
|
23
36
|
|
37
|
+
def parsed
|
38
|
+
@__parsed__ ||= Parser::CurrentRuby.parse(lines.join("\n"))
|
39
|
+
end
|
24
40
|
end
|
@@ -3,20 +3,27 @@ module Lab42::Literate::GroupDoctest
|
|
3
3
|
Ex = Lab42::Literate::Extractor
|
4
4
|
|
5
5
|
def doctest filename
|
6
|
-
|
7
|
-
|
6
|
+
blocks = Ex
|
7
|
+
.extract(File.readlines(filename))
|
8
|
+
|
9
|
+
setups, examples = blocks.partition(&:given?)
|
10
|
+
setups.each{ |setup| make_setup filename, setup }
|
11
|
+
examples.each{ |example| make_context filename, example }
|
8
12
|
end
|
9
13
|
|
10
14
|
private
|
11
15
|
|
12
|
-
def make_context filename,
|
13
|
-
return if
|
14
|
-
title =
|
16
|
+
def make_context filename, example
|
17
|
+
return if example.lines.empty?
|
18
|
+
title = example.get_title "literate block in #{filename}:#{example.range.inspect}"
|
15
19
|
context title do
|
16
20
|
it do
|
17
|
-
eval(
|
21
|
+
eval(example.lines.join("\n"))
|
18
22
|
end
|
19
23
|
end
|
20
24
|
end
|
21
25
|
|
26
|
+
def make_setup filename, setup
|
27
|
+
eval(setup.lines.join("\n"))
|
28
|
+
end
|
22
29
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lab42_literate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-12-
|
11
|
+
date: 2017-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.7'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: parser
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.4'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.4'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: cucumber
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|