dokaz 0.0.3 → 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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- OTE0MmZmNzRmMjlkOGE1ZTFmNjRiYjUwYmU5ZDlhNzQzZGE2Mjc4Yg==
5
- data.tar.gz: !binary |-
6
- NTkxNjdlMDk0Mjk5NDZiYmU0ODBlMDE2YjUzYTJjMzliM2YyN2UyZg==
2
+ SHA256:
3
+ metadata.gz: 523736088a32b27b2e16d362c0ebe5cb704eff2153cd6b07a98565b58fd7dc01
4
+ data.tar.gz: c86ec189e60c7eaa6f485ef6b5ee807e5bc245300cff3d759bfb1b9a270b37fd
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- MjI2NDRlZTJkYjlkNWQxYzA0N2UwYWZiZjA0YWYxNzgwZmFkNDJlMWVlNzA2
10
- YWEyNDk0OTZkOGVmYjg5ZDcwNWIxYTc5OGM2ODMzNzRmNTljZTY3Y2VkOGM1
11
- ZmEzZWM5Zjg1NjQ2ZmU2MWZhZTQwYWZjMjE1MDFiNmYzOGY5OGU=
12
- data.tar.gz: !binary |-
13
- Y2JmMGY4ODljN2QxZjE0ODA4ZDYwN2Y4Mjg0MmM1M2EwYWNkYjM1YTBjYzIw
14
- YTU2MTYwMjllOTc1NzgyMzUyODQxZmIyN2Y1NWQyMWNlM2E3ZWFmZmFlNThk
15
- OTcyMjVjMjE5ZmI3ZWUwYTZhZGM5MjE4MTEwYTM0MTA0OGU1ZGY=
6
+ metadata.gz: 31c454210e0d3f8dc5ed652975fe24408c76c2004e743acea40b15b9914b102f759d7e569ce3f0b219e876a7ec07e7773e8ecc79f36abb18e69ca7c0aa925111
7
+ data.tar.gz: b798d663c0acf6c223a90f638c28dec10b52fb2b0b4112bf95a43371cb1bff2b81cf30ea50d2069d01b0665ddb70646660faa3c36466877ebeca08693aa48e15
data/Changelog.md ADDED
@@ -0,0 +1,5 @@
1
+ # Dokaz Changelog
2
+
3
+ ## 0.0.5 -- 2023-02-12
4
+
5
+ * Make it Ruby 3.1-3.2 compatible (rather hacky, but seem to work)
data/bin/dokaz CHANGED
@@ -5,13 +5,10 @@ require 'slop'
5
5
  $:.unshift 'lib'
6
6
  require 'dokaz'
7
7
 
8
- if File.exists?('.dokaz')
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'
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,7 +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', '~> 4'
27
28
 
28
29
  s.add_development_dependency 'rspec', '~> 3'
29
30
  s.add_development_dependency 'rspec-its', '~> 1'
31
+
32
+ s.add_development_dependency 'rake'
33
+ s.add_development_dependency 'rubygems-tasks'
30
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("0")
61
+ BigDecimal.new('0')
61
62
  ```
62
63
 
63
64
  Try to run it with option `--require cgi`.
@@ -1,8 +1,14 @@
1
1
  # encoding: utf-8
2
2
  require 'ansi/code'
3
+ require 'rouge'
3
4
 
4
5
  class Dokaz
5
6
  class Formatter
7
+ def initialize
8
+ @rouge = Rouge::Formatters::Terminal256.new(Rouge::Themes::Molokai.new)
9
+ @lexer = Rouge::Lexers::Ruby.new
10
+ end
11
+
6
12
  def start_block(block)
7
13
  end
8
14
 
@@ -35,6 +41,14 @@ class Dokaz
35
41
  color(:dark, str)
36
42
  end
37
43
 
44
+ def code(str)
45
+ if STDOUT.tty?
46
+ @rouge.format(@lexer.lex(str))
47
+ else
48
+ code
49
+ end
50
+ end
51
+
38
52
  def color(code, str)
39
53
  if STDOUT.tty?
40
54
  ANSI.send(code){str}
@@ -46,6 +60,7 @@ class Dokaz
46
60
 
47
61
  class SpecFormatter < Formatter
48
62
  def initialize
63
+ super
49
64
  @ok = 0
50
65
  @errors = []
51
66
  end
@@ -65,14 +80,14 @@ class Dokaz
65
80
  puts
66
81
  puts
67
82
 
68
- @errors.each do |code, e|
69
- puts code
83
+ @errors.each do |src, e|
84
+ puts code(src)
70
85
  puts( error("#{e.message} (#{e.class})\n " + filter_backtrace(e.backtrace).join("\n ") + "\n"))
71
86
  end
72
87
 
73
88
  puts
74
89
  @errors.each do |code, e|
75
- ln = e.backtrace.first.sub(/:in .*$/, '')
90
+ ln = filter_backtrace(e.backtrace).last.to_s.sub(/:in .*$/, '')
76
91
  puts error("dokaz #{ln}") + comment(" # #{e.message} (#{e.class})")
77
92
  end
78
93
 
@@ -97,16 +112,16 @@ class Dokaz
97
112
  puts "#{block.caption}\n#{'=' * block.caption.size}\n\n"
98
113
  end
99
114
 
100
- def output(code, res, out)
101
- puts code
115
+ def output(src, res, out)
116
+ puts code(src)
102
117
  unless out.empty?
103
- puts comment("# Prints: \n# " + out.split("\n").join("\n# "))
118
+ puts comment("# Prints: \n# " + out.split("\n").join("\n# "))
104
119
  end
105
120
  puts comment("# => " + res.inspect.split("\n").join("\n# "))
106
121
  end
107
122
 
108
- def output_err(code, e)
109
- puts code
123
+ def output_err(src, e)
124
+ puts code(src)
110
125
  puts comment("# Throws: #{e.message} (#{e.class})")
111
126
  end
112
127
 
data/lib/dokaz/parser.rb CHANGED
@@ -1,11 +1,48 @@
1
1
  # encoding: utf-8
2
2
  require 'strscan'
3
+ require 'stringio'
3
4
 
4
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
+
5
36
  class Block
37
+ FakeIRBContext = Struct.new(:local_variables)
38
+
6
39
  attr_reader :code, :line, :file
40
+ attr_reader :statements
41
+
7
42
  def initialize(code, line, file)
8
43
  @code, @line, @file = code, line, file
44
+
45
+ parse!
9
46
  end
10
47
 
11
48
  def end_line
@@ -19,6 +56,35 @@ class Dokaz
19
56
  def inside?(ln)
20
57
  (line..end_line).cover?(ln)
21
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
22
88
  end
23
89
 
24
90
  class Parser
@@ -27,9 +93,11 @@ class Dokaz
27
93
  end
28
94
 
29
95
  def parse
30
- res = []
96
+ blocks = []
31
97
  ln = 0
98
+
32
99
  scanner = StringScanner.new(File.read(@path))
100
+
33
101
  loop do
34
102
  text = scanner.scan_until(/\n```ruby\n/)
35
103
  break unless text
@@ -37,14 +105,14 @@ class Dokaz
37
105
  ln += text.count("\n")
38
106
  code = scanner.scan_until(/\n```\n/)
39
107
  if !code
40
- res << Block.new(scanner.rest, ln, @path)
108
+ blocks << Block.new(scanner.rest, ln, @path)
41
109
  break
42
110
  end
43
- res << Block.new(code.sub(/```\Z/, ''), ln, @path)
111
+ blocks << Block.new(code.sub(/```\Z/, ''), ln, @path)
44
112
  ln += code.count("\n")
45
113
  end
46
114
 
47
- res
115
+ blocks
48
116
  end
49
117
  end
50
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
- lex = RubyLex.new
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(line, TOPLEVEL_BINDING, block.file, block.line + line_no)
52
+ res = eval(st.code, TOPLEVEL_BINDING, block.file, st.line)
46
53
  }
47
- @formatter.output(line, res, out)
48
- rescue => e
49
- @formatter.output_err(line, e)
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,71 +1,113 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dokaz
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
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: 2015-06-19 00:00:00.000000000 Z
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
+ - !ruby/object:Gem::Dependency
42
+ name: rouge
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '4'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '4'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement
44
58
  requirements:
45
- - - ~>
59
+ - - "~>"
46
60
  - !ruby/object:Gem::Version
47
61
  version: '3'
48
62
  type: :development
49
63
  prerelease: false
50
64
  version_requirements: !ruby/object:Gem::Requirement
51
65
  requirements:
52
- - - ~>
66
+ - - "~>"
53
67
  - !ruby/object:Gem::Version
54
68
  version: '3'
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rspec-its
57
71
  requirement: !ruby/object:Gem::Requirement
58
72
  requirements:
59
- - - ~>
73
+ - - "~>"
60
74
  - !ruby/object:Gem::Version
61
75
  version: '1'
62
76
  type: :development
63
77
  prerelease: false
64
78
  version_requirements: !ruby/object:Gem::Requirement
65
79
  requirements:
66
- - - ~>
80
+ - - "~>"
67
81
  - !ruby/object:Gem::Version
68
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'
69
111
  description:
70
112
  email: zverok.offline@gmail.com
71
113
  executables:
@@ -73,6 +115,7 @@ executables:
73
115
  extensions: []
74
116
  extra_rdoc_files: []
75
117
  files:
118
+ - Changelog.md
76
119
  - LICENSE.txt
77
120
  - README.md
78
121
  - bin/dokaz
@@ -94,19 +137,17 @@ require_paths:
94
137
  - lib
95
138
  required_ruby_version: !ruby/object:Gem::Requirement
96
139
  requirements:
97
- - - ! '>='
140
+ - - ">="
98
141
  - !ruby/object:Gem::Version
99
142
  version: '0'
100
143
  required_rubygems_version: !ruby/object:Gem::Requirement
101
144
  requirements:
102
- - - ! '>='
145
+ - - ">="
103
146
  - !ruby/object:Gem::Version
104
147
  version: '0'
105
148
  requirements: []
106
- rubyforge_project:
107
- rubygems_version: 2.4.6
149
+ rubygems_version: 3.1.6
108
150
  signing_key:
109
151
  specification_version: 4
110
152
  summary: Use your documentation as a specification
111
153
  test_files: []
112
- has_rdoc: