Class: Dorian::Eval

Inherits:
Object
  • Object
show all
Defined in:
lib/dorian/eval.rb

Defined Under Namespace

Classes: Return

Constant Summary collapse

COLORS =
{ red: "\e[31m", green: "\e[32m", reset: "\e[0m" }.freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(ruby: nil, it: nil, debug: false, stdout: true, stderr: true, colorize: false, rails: false, returns: false, fast: false) ⇒ Eval

Returns a new instance of Eval.



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/dorian/eval.rb', line 26

def initialize(
  ruby: nil,
  it: nil,
  debug: false,
  stdout: true,
  stderr: true,
  colorize: false,
  rails: false,
  returns: false,
  fast: false
)
  @ruby = ruby.to_s.empty? ? "nil" : ruby
  @it = it.to_s.empty? ? nil : it
  @debug = !!debug
  @stdout = !!stdout
  @stderr = !!stderr
  @colorize = !!colorize
  @rails = !!rails
  @returns = !!returns
  @fast = !!fast
end

Instance Attribute Details

#colorizeObject (readonly)

Returns the value of attribute colorize.



14
15
16
# File 'lib/dorian/eval.rb', line 14

def colorize
  @colorize
end

#debugObject (readonly)

Returns the value of attribute debug.



14
15
16
# File 'lib/dorian/eval.rb', line 14

def debug
  @debug
end

#fastObject (readonly)

Returns the value of attribute fast.



14
15
16
# File 'lib/dorian/eval.rb', line 14

def fast
  @fast
end

#itObject (readonly)

Returns the value of attribute it.



14
15
16
# File 'lib/dorian/eval.rb', line 14

def it
  @it
end

#railsObject (readonly)

Returns the value of attribute rails.



14
15
16
# File 'lib/dorian/eval.rb', line 14

def rails
  @rails
end

#returnsObject (readonly)

Returns the value of attribute returns.



14
15
16
# File 'lib/dorian/eval.rb', line 14

def returns
  @returns
end

#rubyObject (readonly)

Returns the value of attribute ruby.



14
15
16
# File 'lib/dorian/eval.rb', line 14

def ruby
  @ruby
end

#stderrObject (readonly)

Returns the value of attribute stderr.



14
15
16
# File 'lib/dorian/eval.rb', line 14

def stderr
  @stderr
end

#stdoutObject (readonly)

Returns the value of attribute stdout.



14
15
16
# File 'lib/dorian/eval.rb', line 14

def stdout
  @stdout
end

Class Method Details

.evalObject



48
49
50
# File 'lib/dorian/eval.rb', line 48

def self.eval(...)
  new(...).eval
end

Instance Method Details

#colorize?Boolean

Returns:

  • (Boolean)


119
120
121
# File 'lib/dorian/eval.rb', line 119

def colorize?
  !!colorize
end

#colorize_string(string, color) ⇒ Object



204
205
206
207
208
# File 'lib/dorian/eval.rb', line 204

def colorize_string(string, color)
  return string unless color

  [COLORS.fetch(color), string, COLORS.fetch(:reset)].join
end

#debug?Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/dorian/eval.rb', line 107

def debug?
  !!debug
end

#evalObject



52
53
54
# File 'lib/dorian/eval.rb', line 52

def eval
  fast? ? eval_fast : eval_slow
end

#eval_fastObject



56
57
58
# File 'lib/dorian/eval.rb', line 56

def eval_fast
  Return.new(returned: Kernel.eval(full_ruby))
end

#eval_slowObject



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/dorian/eval.rb', line 60

def eval_slow
  read_out, write_out = IO.pipe
  read_err, write_err = IO.pipe

  spawn(write_out: write_out, write_err: write_err)

  write_out.close
  write_err.close

  out = ""
  err = ""

  thread_out =
    Thread.new do
      out +=
        gets(
          read_out,
          print: stdout?,
          method: :puts
        ).to_s until read_out.eof?
    end

  thread_err =
    Thread.new do
      err +=
        gets(
          read_err,
          color: :red,
          print: stderr?,
          method: :warn
        ).to_s until read_err.eof?
    end

  thread_out.join
  thread_err.join

  if returns?
    Return.new(stdout: out, stderr: err, returned: YAML.safe_load(out))
  else
    Return.new(stdout: out, stderr: err)
  end
end

#fast?Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/dorian/eval.rb', line 103

def fast?
  !!fast
end

#full_rubyObject



156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/dorian/eval.rb', line 156

def full_ruby
  full_ruby = "it = #{to_ruby(it)}\n"
  full_ruby +=
    if returns? && slow?
      <<~RUBY
        require "yaml"
        puts (#{ruby}).to_yaml
      RUBY
    else
      <<~RUBY
        #{ruby}
      RUBY
    end

  full_ruby = <<~RUBY if rails?
    require "#{Dir.pwd}/config/environment"
    #{full_ruby}
  RUBY

  full_ruby
end

#gets(read, color: nil, print: true, method: :puts) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/dorian/eval.rb', line 188

def gets(read, color: nil, print: true, method: :puts)
  original_string = read.gets
  return unless original_string

  string = original_string.rstrip
  string = colorize_string(string, color) if colorize? && color

  if method == :puts && print
    puts [prefix, string].join
  elsif method == :warn && print
    warn [prefix, string].join
  end

  original_string
end

#prefixObject



131
132
133
# File 'lib/dorian/eval.rb', line 131

def prefix
  debug? && !returns? && it ? "[#{it}] " : ""
end

#rails?Boolean

Returns:

  • (Boolean)


123
124
125
# File 'lib/dorian/eval.rb', line 123

def rails?
  !!rails
end

#returns?Boolean

Returns:

  • (Boolean)


127
128
129
# File 'lib/dorian/eval.rb', line 127

def returns?
  !!returns
end

#slow?Boolean

Returns:

  • (Boolean)


152
153
154
# File 'lib/dorian/eval.rb', line 152

def slow?
  !fast?
end

#spawn(write_out:, write_err:) ⇒ Object



178
179
180
181
182
183
184
185
186
# File 'lib/dorian/eval.rb', line 178

def spawn(write_out:, write_err:)
  Process.spawn(
    RbConfig.ruby,
    "-e",
    full_ruby,
    out: write_out,
    err: write_err
  )
end

#stderr?Boolean

Returns:

  • (Boolean)


115
116
117
# File 'lib/dorian/eval.rb', line 115

def stderr?
  !!stderr
end

#stdout?Boolean

Returns:

  • (Boolean)


111
112
113
# File 'lib/dorian/eval.rb', line 111

def stdout?
  !!stdout
end

#to_ruby(ruby) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/dorian/eval.rb', line 135

def to_ruby(ruby)
  case ruby
  when Struct
    keys = ruby.to_h.keys.map { |key| to_ruby(key) }
    values = ruby.to_h.values.map { |value| to_ruby(value) }
    "Struct.new(#{keys.join(", ")}).new(#{values.join(", ")})"
  when String, Symbol, NilClass, TrueClass, FalseClass, Float, Integer
    ruby.inspect
  when Array
    "[#{ruby.map { |element| to_ruby(element) }.join(", ")}]"
  when Hash
    "{#{ruby.map { |key, value| "#{to_ruby(key)} => #{to_ruby(value)}" }}}"
  else
    raise "#{ruby.class} not supported"
  end
end