dokaz 0.0.4 → 0.0.5
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 +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:
|