jbarnette / johnson

Johnson wraps JavaScript in a loving Ruby embrace.

This URL has Read+Write access

johnson / bin / johnson
100755 104 lines (80 sloc) 1.933 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
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
102
103
104
#!/usr/bin/env ruby
 
begin
  require "johnson"
rescue LoadError
  require "rubygems"
  require "johnson"
end
 
require "readline"
 
RUNTIME = js = Johnson::Runtime.new
RUNTIME[:alert] = lambda { |m| puts m }
 
EXIT_VERBS = [nil] + %w(exit quit)
 
local_binding = binding
ruby_readline = []
 
def copy_history
  new_history = []
  until Readline::HISTORY.empty?
    new_history.push(Readline::HISTORY.pop)
  end
  new_history
end
 
def paste_history(old_history)
  until old_history.empty?
    Readline::HISTORY << old_history.pop
  end
end
 
def handle_exit(input)
  if EXIT_VERBS.include?(input)
    puts if input.nil?
    exit
  end
end
 
def rescued(&block)
  yield
rescue Exception => e
  puts e.message
  puts e.backtrace.reject { |l| l =~ /bin\/johnson/ }
end
 
def eval_in_js(expression)
  rescued { puts "=> " + RUNTIME.evaluate(expression, "(console)").inspect }
end
 
def eval_in_ruby(expression, bind_to)
  rescued { puts "=> " + eval(expression, bind_to).inspect }
end
 
options = Johnson::CLI::Options.parse!(ARGV)
options.load_paths.each { |d| $LOAD_PATH << d }
options.files_to_preload.each { |f| RUNTIME.load(f) }
 
unless options.files_to_evaluate.empty?
  options.files_to_evaluate.each { |f| RUNTIME.load(f) }
  exit
end
 
unless options.expressions.empty?
  options.expressions.each { |e| RUNTIME.evaluate(e, '-e') }
  exit
end
 
loop do
  input = Readline.readline("js> ", true)
  handle_exit(input)
  
  if input =~ /^rb\s+(.+)$/
    eval_in_ruby($1, local_binding)
    next
  end
  
  if input == "rb"
    js_readline = copy_history
    paste_history(ruby_readline)
    
    loop do
      input = Readline.readline("rb> ", true)
      handle_exit(input)
 
      break if input == "js"
 
      if input =~ /^js\s+(.+)$/
        eval_in_js($1)
        next
      end
 
      eval_in_ruby(input, local_binding)
    end
    
    ruby_readline = copy_history
    paste_history(js_readline)
    next
  end
  
  eval_in_js(input)
end