cli.rb 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. require 'optparse'
  2. require 'ostruct'
  3. module V8
  4. module CLI
  5. def self.run(exename = 'v8', args = [])
  6. options = OpenStruct.new
  7. options.libs = []
  8. options.libdirs = []
  9. parser = OptionParser.new
  10. parser.banner = "Usage: #{exename} [options]"
  11. parser.on("-r", "--require FILE", "load and execute FILE as JavaScript source") {|r| options.libs << r}
  12. parser.on("-i", "--interactive", "interactive mode") {options.interactive = true}
  13. parser.on("-e", "--execute JAVASCRIPT", String, "evaluate JAVASCRIPT and exit") {|src| options.execute = src}
  14. parser.on("--selftest", "check that therubyracer is functioning properly") {options.selftest = true}
  15. parser.on_tail("-v", "--version", "Show version and exit") {options.version_info = true}
  16. parser.on_tail("-h", "--help", "Show this message") do
  17. puts parser
  18. exit
  19. end
  20. begin
  21. parser.parse!(args.dup)
  22. rescue OptionParser::InvalidOption => e
  23. puts "#{exename}: #{e.message}"
  24. exit(1)
  25. end
  26. if options.version_info
  27. require 'libv8'
  28. puts "The Ruby Racer #{V8::VERSION}"
  29. puts "V8 Version #{Libv8::V8_VERSION}"
  30. exit
  31. elsif options.selftest
  32. self.test
  33. end
  34. Context.new(:with => Shell.new) do |cxt|
  35. for libfile in options.libs do
  36. load(cxt,libfile)
  37. end
  38. if options.interactive
  39. repl(cxt, exename)
  40. elsif options.execute
  41. cxt.eval(options.execute, '<execute>')
  42. else
  43. begin
  44. cxt.eval($stdin, '<stdin>')
  45. rescue Interrupt => e
  46. puts; exit
  47. end
  48. end
  49. end
  50. end
  51. def self.load(cxt, libfile)
  52. begin
  53. cxt.load(libfile)
  54. rescue V8::JSError => e
  55. puts e.message
  56. puts e.backtrace(:javascript)
  57. rescue StandardError => e
  58. puts e
  59. end
  60. end
  61. def self.test
  62. begin
  63. require 'rspec'
  64. specs = File.expand_path('../../../spec', __FILE__)
  65. $:.unshift specs
  66. ARGV.clear
  67. ARGV << specs
  68. ::RSpec::Core::Runner.autorun
  69. exit(0)
  70. rescue LoadError => e
  71. puts "selftest requires rspec to be installed (gem install rspec)"
  72. exit(1)
  73. end
  74. end
  75. def self.repl(cxt, exename)
  76. require 'readline'
  77. puts "help() for help. quit() to quit."
  78. puts "The Ruby Racer #{V8::VERSION}"
  79. puts "Vroom Vroom!"
  80. trap("SIGINT") do
  81. puts "^C"
  82. end
  83. loop do
  84. line = Readline.readline("#{exename}> ", true)
  85. begin
  86. result = cxt.eval(line, '<shell>')
  87. puts(result) unless result.nil?
  88. rescue V8::JSError => e
  89. puts e.message
  90. puts e.backtrace(:javascript)
  91. rescue StandardError => e
  92. puts e
  93. puts e.backtrace.join("\n")
  94. end
  95. end
  96. end
  97. class Shell
  98. def to_s
  99. "[object Shell]"
  100. end
  101. def print(string)
  102. puts string
  103. end
  104. def exit(status = 0)
  105. Kernel.exit(status)
  106. end
  107. alias_method :quit, :exit
  108. def help(*args)
  109. <<-HELP
  110. print(msg)
  111. print msg to STDOUT
  112. exit(status = 0)
  113. exit the shell
  114. also: quit()
  115. evalrb(source)
  116. evaluate some ruby source
  117. HELP
  118. end
  119. end
  120. end
  121. end