erudite 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MmMyNDJiNGZhYjc3YmY5NDJmNjA1ZWY2OWZmNDRkMDdiYjAwMzA0MQ==
5
- data.tar.gz: !binary |-
6
- NjA3YjdkZWY3OTVjMDM2OTI2NTUzZWU2YzRhNTViMjI5NmE4NjkxOQ==
2
+ SHA1:
3
+ metadata.gz: 2dcd8553e0a52b455a6437a4fc7f339e744bc4cf
4
+ data.tar.gz: 0bf967f16cc6422116ba59cbbb263b1753c90c8e
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- NjllZjIyNjdkMWE2YjQwNGJmNmUxZTQyYTA5ODFhNmI5OGIxYTllYTU4NDNh
10
- OWM5M2Y2N2ZhMWM0YzIxNzI4NzdjOTI3MTQ0YTFlNjdlNzU2ZjhhMjNmZDE4
11
- ZDhhMWU1NTc5NzUwY2Q0ZWIxYzVmNDEzZjQzOGE1OWMxNzY4OTU=
12
- data.tar.gz: !binary |-
13
- MThjNzM2YTllMTY2NzBkNGY4ZjYwZTRmODljMGE1YTkzOGNmYmMzYzQzMDg4
14
- N2Y1YzIwY2I4Y2JiMmJmNGVmMTBiMWQwMTY4YjIzZDcxMzk5NmJmZWQ4ZDFh
15
- YjhlMGMyOTBmMjVkOTYyYzZkZTI3YTY1NWU1MDI4YzRlMGY2NzY=
6
+ metadata.gz: 38b880bc0c05e713911ce85df61a43082db3446cd8a63093b0c85a338eb46aa4190590712b76d7136f924de874a610293e88a21812897b3dbb4d5d566e98f2cf
7
+ data.tar.gz: 79c25e231334d1d254f7f88fcb8803ed9273ca150d745babe1876cb3d0e3e8009fb65cf187840bcc759844b41b7d2968c2bd790d2f3e01bab09fc8a97277642c
@@ -1 +1,9 @@
1
1
  # Changelog
2
+
3
+ ## v0.2.0 (2014-09-18)
4
+
5
+ - Create an executable.
6
+
7
+ ## v0.1.0 (2014-08-24)
8
+
9
+ - Initial release.
data/LICENSE.md CHANGED
@@ -1,18 +1,18 @@
1
- Copyright (c) 2014 Taylor Fausak <taylor@fausak.me>
2
-
3
- Permission is hereby granted, free of charge, to any person obtaining a copy of
4
- this software and associated documentation files (the "Software"), to deal in
5
- the Software without restriction, including without limitation the rights to
6
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
- the Software, and to permit persons to whom the Software is furnished to do so,
8
- subject to the following conditions:
9
-
10
- The above copyright notice and this permission notice shall be included in all
11
- copies or substantial portions of the Software.
12
-
13
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
- FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
- COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
- IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1
+ Copyright (c) 2014 Taylor Fausak <taylor@fausak.me>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the "Software"), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
7
+ the Software, and to permit persons to whom the Software is furnished to do so,
8
+ subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
15
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
16
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
17
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,9 +1,36 @@
1
1
  # [Erudite][1]
2
2
 
3
+ [![Gem version][2]][3]
4
+ [![Build status][4]][5]
5
+ [![Code coverage][6]][7]
6
+ [![Code quality][8]][9]
7
+ [![Dependency status][10]][11]
8
+
3
9
  Executable documentation.
4
10
 
11
+ - [Installation](#installation)
12
+ - [Usage](#usage)
13
+
14
+ ## Installation
15
+
16
+ Add it to your Gemfile:
17
+
5
18
  ``` rb
6
- examples = Erudite::Parser.parse(<<-'RUBY')
19
+ gem 'erudite', '~> 0.2.0'
20
+ ```
21
+
22
+ Or install it manually:
23
+
24
+ ``` sh
25
+ $ gem install erudite --version 0.2.0
26
+ ```
27
+
28
+ This project uses [Semantic Versioning][12].
29
+
30
+ ## Usage
31
+
32
+ ``` irb
33
+ # example.irb
7
34
  >> 1 + 2
8
35
  => 3
9
36
 
@@ -21,8 +48,8 @@ hello world
21
48
  oh noes
22
49
  => nil
23
50
 
24
- >> fail 'catastrophe!'
25
- RuntimeError: catastrophe!
51
+ >> fail 'catastrophe'
52
+ RuntimeError: catastrophe
26
53
 
27
54
  >> puts 'chunky
28
55
  .. bacon'
@@ -35,19 +62,30 @@ bacon
35
62
  .. end
36
63
  >> double(3)
37
64
  => 6
38
- RUBY
39
-
40
- examples.each do |example|
41
- if example.pass?
42
- puts 'PASS'
43
- else
44
- puts 'FAIL'
45
- puts " expected : #{example.expected.result.inspect}"
46
- puts " : #{example.expected.output.inspect}"
47
- puts " actual : #{example.actual.result.inspect}"
48
- puts " : #{example.actual.output.inspect}"
49
- end
50
- end
65
+ ```
66
+
67
+ ``` sh
68
+ $ erudite example.irb
69
+ - PASS
70
+ - PASS
71
+ - PASS
72
+ - PASS
73
+ - PASS
74
+ - PASS
75
+ - PASS
76
+ - PASS
77
+ - PASS
51
78
  ```
52
79
 
53
80
  [1]: https://github.com/tfausak/erudite
81
+ [2]: https://badge.fury.io/rb/erudite.svg
82
+ [3]: http://rubygems.org/gems/erudite
83
+ [4]: https://travis-ci.org/tfausak/erudite.svg
84
+ [5]: https://travis-ci.org/tfausak/erudite
85
+ [6]: https://img.shields.io/coveralls/tfausak/erudite.svg
86
+ [7]: https://coveralls.io/r/tfausak/erudite
87
+ [8]: https://codeclimate.com/github/tfausak/erudite/badges/gpa.svg
88
+ [9]: https://codeclimate.com/github/tfausak/erudite
89
+ [10]: https://gemnasium.com/tfausak/erudite.svg
90
+ [11]: https://gemnasium.com/tfausak/erudite
91
+ [12]: http://semver.org/spec/v2.0.0.html
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # coding: utf-8
3
+
4
+ require 'erudite'
5
+
6
+ Erudite::Executable.run(ARGF)
@@ -1,9 +1,10 @@
1
- # coding: utf-8
2
-
3
- require 'erudite/example'
4
- require 'erudite/outcome'
5
- require 'erudite/parser'
6
-
7
- # Executable documentation.
8
- module Erudite
9
- end
1
+ # coding: utf-8
2
+
3
+ require 'erudite/example'
4
+ require 'erudite/executable'
5
+ require 'erudite/outcome'
6
+ require 'erudite/parser'
7
+
8
+ # Executable documentation.
9
+ module Erudite
10
+ end
@@ -1,79 +1,82 @@
1
- # coding: utf-8
2
-
3
- require 'stringio'
4
-
5
- module Erudite
6
- # Code to be run and compared against its expected outcome.
7
- class Example
8
- attr_reader :source
9
- attr_reader :expected
10
- attr_writer :binding
11
-
12
- def initialize(source, result = nil, output = nil)
13
- @source = source
14
- @expected = Outcome.new(result, output)
15
- end
16
-
17
- def binding
18
- @binding ||= TOPLEVEL_BINDING.dup
19
- end
20
-
21
- def run!
22
- binding.eval(source, __FILE__, __LINE__)
23
- end
24
-
25
- def run
26
- [run!, nil]
27
- rescue Exception => exception # rubocop:disable Lint/RescueException
28
- [nil, exception]
29
- end
30
-
31
- def self.without_stdio
32
- stdin, stdout, stderr = $stdin, $stdout, $stderr
33
- $stdin = $stdout = $stderr = io = StringIO.new
34
- [yield, io]
35
- ensure
36
- $stdin, $stdout, $stderr = stdin, stdout, stderr
37
- end
38
-
39
- def self.format_exception(exception)
40
- "#{exception.class.name}: #{exception.message}"
41
- end
42
-
43
- def actual
44
- return @actual if defined?(@actual)
45
-
46
- result, io = self.class.without_stdio do
47
- result, exception = run
48
- warn(self.class.format_exception(exception)) if exception
49
- result.inspect
50
- end
51
-
52
- @actual = Outcome.new(result, io.string)
53
- end
54
-
55
- def self.pattern(string)
56
- Regexp.new(Regexp.escape(string).gsub('\.\.\.', '.*?'))
57
- end
58
-
59
- def valid_result?
60
- return true unless expected.result
61
- self.class.pattern(expected.result).match(actual.result)
62
- end
63
-
64
- def valid_output?
65
- return true unless expected.output
66
- self.class.pattern(expected.output).match(actual.output)
67
- end
68
-
69
- def pass?
70
- actual
71
- valid_result? && valid_output?
72
- end
73
-
74
- def ==(other)
75
- source == other.source &&
76
- expected == other.expected
77
- end
78
- end
79
- end
1
+ # coding: utf-8
2
+
3
+ require 'English'
4
+ require 'stringio'
5
+
6
+ module Erudite
7
+ # Code to be run and compared against its expected outcome.
8
+ class Example
9
+ attr_reader :source
10
+ attr_reader :expected
11
+ attr_writer :binding
12
+
13
+ def initialize(source, result = nil, output = nil)
14
+ @source = source
15
+ @expected = Outcome.new(result, output)
16
+ end
17
+
18
+ def binding
19
+ @binding ||= TOPLEVEL_BINDING.dup
20
+ end
21
+
22
+ def run!
23
+ binding.eval(source, __FILE__, __LINE__)
24
+ end
25
+
26
+ def run
27
+ [run!, nil]
28
+ rescue Exception => exception # rubocop:disable Lint/RescueException
29
+ [nil, exception]
30
+ end
31
+
32
+ def self.without_stdio
33
+ stdin, stdout, stderr, argv = $stdin, $stdout, $stderr, $ARGV.dup
34
+ io = $stdin = $stdout = $stderr = StringIO.new
35
+ $ARGV.clear
36
+ [yield, io]
37
+ ensure
38
+ $stdin, $stdout, $stderr = stdin, stdout, stderr
39
+ $ARGV.replace(argv)
40
+ end
41
+
42
+ def self.format_exception(exception)
43
+ "#{exception.class.name}: #{exception.message}"
44
+ end
45
+
46
+ def actual
47
+ return @actual if defined?(@actual)
48
+
49
+ result, io = self.class.without_stdio do
50
+ result, exception = run
51
+ warn(self.class.format_exception(exception)) if exception
52
+ result.inspect
53
+ end
54
+
55
+ @actual = Outcome.new(result, io.string)
56
+ end
57
+
58
+ def self.pattern(string)
59
+ Regexp.new(Regexp.escape(string).gsub('\.\.\.', '.*?'))
60
+ end
61
+
62
+ def valid_result?
63
+ return true unless expected.result
64
+ self.class.pattern(expected.result).match(actual.result)
65
+ end
66
+
67
+ def valid_output?
68
+ return true unless expected.output
69
+ self.class.pattern(expected.output).match(actual.output)
70
+ end
71
+
72
+ def pass?
73
+ actual
74
+ valid_result? && valid_output?
75
+ end
76
+
77
+ def ==(other)
78
+ source == other.source &&
79
+ expected == other.expected
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+
3
+ module Erudite
4
+ # Parses, runs, and outputs examples.
5
+ class Executable
6
+ def self.run(io)
7
+ Parser.parse(io).each { |example| puts format_example(example) }
8
+ end
9
+
10
+ def self.format_example(example)
11
+ if example.pass?
12
+ format_passing_example(example)
13
+ else
14
+ format_failing_example(example)
15
+ end
16
+ end
17
+
18
+ def self.format_passing_example(_example)
19
+ '- PASS'
20
+ end
21
+
22
+ def self.format_failing_example(example)
23
+ <<-TXT
24
+ - FAIL
25
+ Source: #{example.source}
26
+ Expected:
27
+ Output: #{example.expected.output.inspect}
28
+ Result: #{example.expected.result.inspect}
29
+ Actual:
30
+ Output: #{example.actual.output.inspect}
31
+ Result: #{example.actual.result.inspect}
32
+ TXT
33
+ end
34
+ end
35
+ end
@@ -1,19 +1,19 @@
1
- # coding: utf-8
2
-
3
- module Erudite
4
- # Information about an expected or actual outcome.
5
- class Outcome
6
- attr_reader :result
7
- attr_reader :output
8
-
9
- def initialize(result, output)
10
- @result = result
11
- @output = output
12
- end
13
-
14
- def ==(other)
15
- result == other.result &&
16
- output == other.output
17
- end
18
- end
19
- end
1
+ # coding: utf-8
2
+
3
+ module Erudite
4
+ # Information about an expected or actual outcome.
5
+ class Outcome
6
+ attr_reader :result
7
+ attr_reader :output
8
+
9
+ def initialize(result, output)
10
+ @result = result
11
+ @output = output
12
+ end
13
+
14
+ def ==(other)
15
+ result == other.result &&
16
+ output == other.output
17
+ end
18
+ end
19
+ end
@@ -1,54 +1,54 @@
1
- # coding: utf-8
2
-
3
- module Erudite
4
- # Parses IRB output into examples.
5
- class Parser
6
- def self.parse(string)
7
- group(string).map { |lines| exemplify(lines) }
8
- end
9
-
10
- def self.group(string)
11
- buffer = []
12
-
13
- groups = string.each_line.each_with_object([]) do |line, array|
14
- if line.start_with?('>> ') && !buffer.empty?
15
- array.push(buffer)
16
- buffer = []
17
- end
18
-
19
- buffer.push(line)
20
- end
21
-
22
- buffer.empty? ? groups : groups.push(buffer)
23
- end
24
-
25
- def self.exemplify(lines)
26
- source = extract_source(lines)
27
- result = extract_result(lines)
28
- output = extract_output(lines)
29
-
30
- Example.new(source, result, output)
31
- end
32
-
33
- def self.extract_source(lines)
34
- source = lines
35
- .select { |line| line.start_with?('>> ', '.. ') }
36
- .map { |line| line[3..-1].chomp }
37
- source.join("\n") unless source.empty?
38
- end
39
-
40
- def self.extract_result(lines)
41
- result = lines
42
- .select { |line| line.start_with?('=> ') }
43
- .map { |line| line[3..-1].chomp }
44
- result.join("\n") unless result.empty?
45
- end
46
-
47
- def self.extract_output(lines)
48
- output = lines
49
- .reject { |line| line.start_with?('>> ', '.. ', '=> ') }
50
- .map { |line| line.chomp }
51
- output.join("\n") unless output.empty?
52
- end
53
- end
54
- end
1
+ # coding: utf-8
2
+
3
+ module Erudite
4
+ # Parses IRB output into examples.
5
+ class Parser
6
+ def self.parse(string)
7
+ group(string).map { |lines| exemplify(lines) }
8
+ end
9
+
10
+ def self.group(string)
11
+ buffer = []
12
+
13
+ groups = string.each_line.each_with_object([]) do |line, array|
14
+ if line.start_with?('>> ') && !buffer.empty?
15
+ array.push(buffer)
16
+ buffer = []
17
+ end
18
+
19
+ buffer.push(line)
20
+ end
21
+
22
+ buffer.empty? ? groups : groups.push(buffer)
23
+ end
24
+
25
+ def self.exemplify(lines)
26
+ source = extract_source(lines)
27
+ result = extract_result(lines)
28
+ output = extract_output(lines)
29
+
30
+ Example.new(source, result, output)
31
+ end
32
+
33
+ def self.extract_source(lines)
34
+ source = lines
35
+ .select { |line| line.start_with?('>> ', '.. ') }
36
+ .map { |line| line[3..-1].chomp }
37
+ source.join("\n") unless source.empty?
38
+ end
39
+
40
+ def self.extract_result(lines)
41
+ result = lines
42
+ .select { |line| line.start_with?('=> ') }
43
+ .map { |line| line[3..-1].chomp }
44
+ result.join("\n") unless result.empty?
45
+ end
46
+
47
+ def self.extract_output(lines)
48
+ output = lines
49
+ .reject { |line| line.start_with?('>> ', '.. ', '=> ') }
50
+ .map(&:chomp)
51
+ output.join("\n") unless output.empty?
52
+ end
53
+ end
54
+ end