dokaz 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/Changelog.md +5 -0
- data/bin/dokaz +8 -4
- data/dokaz.gemspec +5 -2
- data/examples/README.md +2 -1
- data/lib/dokaz/formatters.rb +7 -7
- data/lib/dokaz/parser.rb +71 -4
- data/lib/dokaz.rb +14 -7
- metadata +46 -19
checksums.yaml
CHANGED
@@ -1,15 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
|
5
|
-
data.tar.gz: !binary |-
|
6
|
-
YWY4ZGM3MDZmYjQ5ZWJiZmNkZjVmMzc2NWVhZGY5ZjM3YWZjMzJiMQ==
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 523736088a32b27b2e16d362c0ebe5cb704eff2153cd6b07a98565b58fd7dc01
|
4
|
+
data.tar.gz: c86ec189e60c7eaa6f485ef6b5ee807e5bc245300cff3d759bfb1b9a270b37fd
|
7
5
|
SHA512:
|
8
|
-
metadata.gz:
|
9
|
-
|
10
|
-
MmYzNjRmZTRlNjdjNjQ3OWY3YTg2OGNiNDAxZTJjOTdjYjBhMTI0NjNjOWY0
|
11
|
-
NzkzMmVhZTAzMzA1NzlmNTNjOWFiZjVlYThlMzQ0NGE5NmM2ZGI=
|
12
|
-
data.tar.gz: !binary |-
|
13
|
-
MjhkNTU2YWQ3ZTMwN2JlNjMyOTEzNjAzMjRjYzE3MDMyZjEzZmY1Y2RiNGY3
|
14
|
-
OGRkM2JhZjg5ZjJhZjVhMWY1NDNkZjExM2E5ZDc3ODc4YTY1MDAzYTI1YWY4
|
15
|
-
NmQ3NmYyNTEyMWRkMWNlY2Q1Mjk2ZDQ0OTAxMDQyM2EwMTk5ZDM=
|
6
|
+
metadata.gz: 31c454210e0d3f8dc5ed652975fe24408c76c2004e743acea40b15b9914b102f759d7e569ce3f0b219e876a7ec07e7773e8ecc79f36abb18e69ca7c0aa925111
|
7
|
+
data.tar.gz: b798d663c0acf6c223a90f638c28dec10b52fb2b0b4112bf95a43371cb1bff2b81cf30ea50d2069d01b0665ddb70646660faa3c36466877ebeca08693aa48e15
|
data/Changelog.md
ADDED
data/bin/dokaz
CHANGED
@@ -5,13 +5,10 @@ require 'slop'
|
|
5
5
|
$:.unshift 'lib'
|
6
6
|
require 'dokaz'
|
7
7
|
|
8
|
-
if File.
|
8
|
+
if File.exist?('.dokaz')
|
9
9
|
ARGV.push(*File.read('.dokaz').split(/\s+/m))
|
10
10
|
end
|
11
11
|
|
12
|
-
patterns = []
|
13
|
-
patterns << ARGV.shift until ARGV.empty? || ARGV.first =~ /^-/
|
14
|
-
|
15
12
|
HELP = %Q{
|
16
13
|
Usage: dokaz [patterns] [options]
|
17
14
|
|
@@ -26,12 +23,19 @@ Options:
|
|
26
23
|
--help Shows this message
|
27
24
|
}
|
28
25
|
|
26
|
+
patterns = []
|
27
|
+
patterns << ARGV.shift until ARGV.empty? || ARGV.first =~ /^-/
|
28
|
+
|
29
29
|
options = Slop.parse do
|
30
30
|
on :r, :require=, "Additional files to require, comma-separated"
|
31
31
|
on :f, :format=, "Output format (spec or show[case])"
|
32
32
|
on :help
|
33
33
|
end
|
34
34
|
|
35
|
+
if patterns.empty?
|
36
|
+
patterns.concat(Dir['README.{md,markdown}'])
|
37
|
+
end
|
38
|
+
|
35
39
|
if patterns.empty? || options.help?
|
36
40
|
puts HELP
|
37
41
|
exit
|
data/dokaz.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'dokaz'
|
3
|
-
s.version = '0.0.
|
3
|
+
s.version = '0.0.5'
|
4
4
|
s.authors = ['Victor Shepelev']
|
5
5
|
s.email = 'zverok.offline@gmail.com'
|
6
6
|
s.homepage = 'https://github.com/zverok/dokaz'
|
@@ -24,8 +24,11 @@ Gem::Specification.new do |s|
|
|
24
24
|
|
25
25
|
s.add_dependency 'ansi'
|
26
26
|
s.add_dependency 'slop', '~> 3'
|
27
|
-
s.add_dependency 'rouge'
|
27
|
+
s.add_dependency 'rouge', '~> 4'
|
28
28
|
|
29
29
|
s.add_development_dependency 'rspec', '~> 3'
|
30
30
|
s.add_development_dependency 'rspec-its', '~> 1'
|
31
|
+
|
32
|
+
s.add_development_dependency 'rake'
|
33
|
+
s.add_development_dependency 'rubygems-tasks'
|
31
34
|
end
|
data/examples/README.md
CHANGED
@@ -51,13 +51,14 @@ puts a.sum(10)
|
|
51
51
|
This code throws an error:
|
52
52
|
|
53
53
|
```ruby
|
54
|
+
# It's a comment, but not seen while evaluating
|
54
55
|
100 / 0
|
55
56
|
```
|
56
57
|
|
57
58
|
This code requires additional require:
|
58
59
|
|
59
60
|
```ruby
|
60
|
-
BigDecimal.new(
|
61
|
+
BigDecimal.new('0')
|
61
62
|
```
|
62
63
|
|
63
64
|
Try to run it with option `--require cgi`.
|
data/lib/dokaz/formatters.rb
CHANGED
@@ -5,7 +5,7 @@ require 'rouge'
|
|
5
5
|
class Dokaz
|
6
6
|
class Formatter
|
7
7
|
def initialize
|
8
|
-
@rouge = Rouge::Formatters::Terminal256.new
|
8
|
+
@rouge = Rouge::Formatters::Terminal256.new(Rouge::Themes::Molokai.new)
|
9
9
|
@lexer = Rouge::Lexers::Ruby.new
|
10
10
|
end
|
11
11
|
|
@@ -45,7 +45,7 @@ class Dokaz
|
|
45
45
|
if STDOUT.tty?
|
46
46
|
@rouge.format(@lexer.lex(str))
|
47
47
|
else
|
48
|
-
code
|
48
|
+
code
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
@@ -81,13 +81,13 @@ class Dokaz
|
|
81
81
|
puts
|
82
82
|
|
83
83
|
@errors.each do |src, e|
|
84
|
-
|
84
|
+
puts code(src)
|
85
85
|
puts( error("#{e.message} (#{e.class})\n " + filter_backtrace(e.backtrace).join("\n ") + "\n"))
|
86
86
|
end
|
87
87
|
|
88
88
|
puts
|
89
89
|
@errors.each do |code, e|
|
90
|
-
ln = e.backtrace.
|
90
|
+
ln = filter_backtrace(e.backtrace).last.to_s.sub(/:in .*$/, '')
|
91
91
|
puts error("dokaz #{ln}") + comment(" # #{e.message} (#{e.class})")
|
92
92
|
end
|
93
93
|
|
@@ -113,15 +113,15 @@ class Dokaz
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def output(src, res, out)
|
116
|
-
|
116
|
+
puts code(src)
|
117
117
|
unless out.empty?
|
118
|
-
puts comment("# Prints: \n# " + out.split("\n").join("\n#
|
118
|
+
puts comment("# Prints: \n# " + out.split("\n").join("\n# "))
|
119
119
|
end
|
120
120
|
puts comment("# => " + res.inspect.split("\n").join("\n# "))
|
121
121
|
end
|
122
122
|
|
123
123
|
def output_err(src, e)
|
124
|
-
|
124
|
+
puts code(src)
|
125
125
|
puts comment("# Throws: #{e.message} (#{e.class})")
|
126
126
|
end
|
127
127
|
|
data/lib/dokaz/parser.rb
CHANGED
@@ -3,10 +3,46 @@ require 'strscan'
|
|
3
3
|
require 'stringio'
|
4
4
|
|
5
5
|
class Dokaz
|
6
|
+
class Statement
|
7
|
+
attr_reader :code, :line, :block
|
8
|
+
attr_reader :pre_comment
|
9
|
+
attr_accessor :comment
|
10
|
+
|
11
|
+
def initialize(code, line, block)
|
12
|
+
@raw_code, @line, @block = code, line, block
|
13
|
+
@comment = ''
|
14
|
+
|
15
|
+
parse!
|
16
|
+
end
|
17
|
+
|
18
|
+
def empty?
|
19
|
+
code.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def parse!
|
25
|
+
pre_lines = []
|
26
|
+
lines = @raw_code.split("\n")
|
27
|
+
while !lines.empty? && (lines.first =~ /^\s*\#/ || lines.first.strip.empty?)
|
28
|
+
pre_lines << lines.shift
|
29
|
+
@line += 1
|
30
|
+
end
|
31
|
+
@code = lines.join("\n")
|
32
|
+
@pre_comment = pre_lines.reject{|ln| ln.strip.empty?}.join("\n")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
6
36
|
class Block
|
37
|
+
FakeIRBContext = Struct.new(:local_variables)
|
38
|
+
|
7
39
|
attr_reader :code, :line, :file
|
40
|
+
attr_reader :statements
|
41
|
+
|
8
42
|
def initialize(code, line, file)
|
9
43
|
@code, @line, @file = code, line, file
|
44
|
+
|
45
|
+
parse!
|
10
46
|
end
|
11
47
|
|
12
48
|
def end_line
|
@@ -20,6 +56,35 @@ class Dokaz
|
|
20
56
|
def inside?(ln)
|
21
57
|
(line..end_line).cover?(ln)
|
22
58
|
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def parse!
|
63
|
+
@statements = []
|
64
|
+
lex = RubyLex.new
|
65
|
+
|
66
|
+
# We do unholy things by reusing IRB's internal helper classes.
|
67
|
+
# In 3.2 (ver.1.6), IRB changed them to be more complicated. I only had
|
68
|
+
# time to quick-hack it around with fake copies of object IRB use.
|
69
|
+
# It might fail anytime, but works on test examples :shrug:
|
70
|
+
if IRB::VERSION >= '1.6'
|
71
|
+
ctx = FakeIRBContext.new(local_variables: [])
|
72
|
+
lex.set_input(SpecIO.new(code), context: ctx)
|
73
|
+
lex.each_top_level_statement(ctx) do |st, line_no|
|
74
|
+
@statements << Statement.new(st, line + line_no, self)
|
75
|
+
end
|
76
|
+
else
|
77
|
+
lex.set_input(SpecIO.new(code))
|
78
|
+
lex.each_top_level_statement do |st, line_no|
|
79
|
+
@statements << Statement.new(st, line + line_no, self)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
@statements.each_cons(2){|s1, s2|
|
84
|
+
s1.comment = s2.pre_comment
|
85
|
+
}
|
86
|
+
@statements.reject!(&:empty?)
|
87
|
+
end
|
23
88
|
end
|
24
89
|
|
25
90
|
class Parser
|
@@ -28,9 +93,11 @@ class Dokaz
|
|
28
93
|
end
|
29
94
|
|
30
95
|
def parse
|
31
|
-
|
96
|
+
blocks = []
|
32
97
|
ln = 0
|
98
|
+
|
33
99
|
scanner = StringScanner.new(File.read(@path))
|
100
|
+
|
34
101
|
loop do
|
35
102
|
text = scanner.scan_until(/\n```ruby\n/)
|
36
103
|
break unless text
|
@@ -38,14 +105,14 @@ class Dokaz
|
|
38
105
|
ln += text.count("\n")
|
39
106
|
code = scanner.scan_until(/\n```\n/)
|
40
107
|
if !code
|
41
|
-
|
108
|
+
blocks << Block.new(scanner.rest, ln, @path)
|
42
109
|
break
|
43
110
|
end
|
44
|
-
|
111
|
+
blocks << Block.new(code.sub(/```\Z/, ''), ln, @path)
|
45
112
|
ln += code.count("\n")
|
46
113
|
end
|
47
114
|
|
48
|
-
|
115
|
+
blocks
|
49
116
|
end
|
50
117
|
end
|
51
118
|
end
|
data/lib/dokaz.rb
CHANGED
@@ -11,6 +11,13 @@ class Dokaz
|
|
11
11
|
'show' => ShowcaseFormatter,
|
12
12
|
'showcase' => ShowcaseFormatter
|
13
13
|
}
|
14
|
+
|
15
|
+
class << self
|
16
|
+
def before(&block)
|
17
|
+
return @before || ->(){} unless block
|
18
|
+
@before = block
|
19
|
+
end
|
20
|
+
end
|
14
21
|
|
15
22
|
def initialize(patterns, options = {})
|
16
23
|
@blocks = select_blocks(patterns)
|
@@ -23,6 +30,8 @@ class Dokaz
|
|
23
30
|
end
|
24
31
|
|
25
32
|
def run
|
33
|
+
self.class.before.call
|
34
|
+
|
26
35
|
puts "Running #{@blocks.count} blocks from #{@blocks.map(&:file).uniq.count} files\n\n"
|
27
36
|
|
28
37
|
@blocks.each do |b|
|
@@ -36,17 +45,15 @@ class Dokaz
|
|
36
45
|
private
|
37
46
|
|
38
47
|
def process_block(block)
|
39
|
-
|
40
|
-
lex.set_input(SpecIO.new(block.code))
|
41
|
-
lex.each_top_level_statement do |line, line_no|
|
48
|
+
block.statements.each do |st|
|
42
49
|
begin
|
43
50
|
res = nil
|
44
51
|
out = capture_output{
|
45
|
-
res = eval(
|
52
|
+
res = eval(st.code, TOPLEVEL_BINDING, block.file, st.line)
|
46
53
|
}
|
47
|
-
@formatter.output(
|
48
|
-
rescue => e
|
49
|
-
@formatter.output_err(
|
54
|
+
@formatter.output(st.code, res, out)
|
55
|
+
rescue Exception => e
|
56
|
+
@formatter.output_err(st.code, e)
|
50
57
|
break
|
51
58
|
end
|
52
59
|
end
|
metadata
CHANGED
@@ -1,85 +1,113 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dokaz
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Victor Shepelev
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ansi
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: slop
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '3'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rouge
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '4'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '4'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - ~>
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '3'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - ~>
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '3'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec-its
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - ~>
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '1'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - ~>
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubygems-tasks
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
83
111
|
description:
|
84
112
|
email: zverok.offline@gmail.com
|
85
113
|
executables:
|
@@ -87,6 +115,7 @@ executables:
|
|
87
115
|
extensions: []
|
88
116
|
extra_rdoc_files: []
|
89
117
|
files:
|
118
|
+
- Changelog.md
|
90
119
|
- LICENSE.txt
|
91
120
|
- README.md
|
92
121
|
- bin/dokaz
|
@@ -108,19 +137,17 @@ require_paths:
|
|
108
137
|
- lib
|
109
138
|
required_ruby_version: !ruby/object:Gem::Requirement
|
110
139
|
requirements:
|
111
|
-
- -
|
140
|
+
- - ">="
|
112
141
|
- !ruby/object:Gem::Version
|
113
142
|
version: '0'
|
114
143
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
115
144
|
requirements:
|
116
|
-
- -
|
145
|
+
- - ">="
|
117
146
|
- !ruby/object:Gem::Version
|
118
147
|
version: '0'
|
119
148
|
requirements: []
|
120
|
-
|
121
|
-
rubygems_version: 2.4.6
|
149
|
+
rubygems_version: 3.1.6
|
122
150
|
signing_key:
|
123
151
|
specification_version: 4
|
124
152
|
summary: Use your documentation as a specification
|
125
153
|
test_files: []
|
126
|
-
has_rdoc:
|