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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- YmVmYmJhOGQ4YWFjNWM2MDg3ZjIxODcxOGNkYjc0Yjg4ZGY2ODUzOA==
5
- data.tar.gz: !binary |-
6
- YWY4ZGM3MDZmYjQ5ZWJiZmNkZjVmMzc2NWVhZGY5ZjM3YWZjMzJiMQ==
2
+ SHA256:
3
+ metadata.gz: 523736088a32b27b2e16d362c0ebe5cb704eff2153cd6b07a98565b58fd7dc01
4
+ data.tar.gz: c86ec189e60c7eaa6f485ef6b5ee807e5bc245300cff3d759bfb1b9a270b37fd
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- YjQ4YzBlMThjZmJiN2Y0NjQ0MDRjZmMyYTM2Yjg4NjRiOWRlNTk0YzNjNGY5
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
@@ -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.4'
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("0")
61
+ BigDecimal.new('0')
61
62
  ```
62
63
 
63
64
  Try to run it with option `--require cgi`.
@@ -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 + "\n"
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
- print code(src)
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.first.sub(/:in .*$/, '')
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
- print code(src)
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
- print code(src)
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
- res = []
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
- res << Block.new(scanner.rest, ln, @path)
108
+ blocks << Block.new(scanner.rest, ln, @path)
42
109
  break
43
110
  end
44
- res << Block.new(code.sub(/```\Z/, ''), ln, @path)
111
+ blocks << Block.new(code.sub(/```\Z/, ''), ln, @path)
45
112
  ln += code.count("\n")
46
113
  end
47
114
 
48
- res
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
- 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,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
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-21 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
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: '0'
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: '0'
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
- rubyforge_project:
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: