dokaz 0.0.3 → 0.0.5

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
- 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: