Report abuse

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
require "escape"
require "web_preview"

require 'open3'
require 'cgi'
require 'fcntl'

$SCRIPTMATE_VERSION = "$Revision: 6031 $"

class UserScript
  # execmatch will be substituted into the #! match.  so write a regular
  # expression that can recognize the language you want to run.
  # in python, we:
  #  @@execmatch = "python(\d.\d)?"
  @@execmatch = ""
  # @@execargs is an array of arguments you want to pass to the executable.
  @@execargs = []
  def initialize
    @content = STDIN.read
    @arg0 = $1       if @content =~ /\A#!([^ \n]*(?:env\s+)?#{@@execmatch})/
    @args = $1.split if @content =~ /\A#![^ \n]*(?:env\s+)?#{@@execmatch}[ \t]+(.*)$/
    if ENV.has_key? 'TM_FILEPATH' then
      @path = ENV['TM_FILEPATH']
      @display_name = File.basename(@path)
      # save file
      open(@path, "w") { |io| io.write @content }
    else
      @path = '-'
      @display_name = 'untitled'
    end
  end

  def executable
    # return the path to the executable that will run @content.
  end

  def version_string
    # return the version string of the executable.
  end

  def run
    rd, wr = IO.pipe
    rd.fcntl(Fcntl::F_SETFD, 1)
    ENV['TM_ERROR_FD'] = wr.to_i.to_s
    args = [executable, @@execargs, Array(@args), @path, ARGV.to_a ].flatten
    stdin, stdout, stderr = Open3.popen3(args.join(" "))
    Thread.new { stdin.write @content; stdin.close } unless ENV.has_key? 'TM_FILEPATH'
    wr.close
    [ stdout, stderr, rd ]
  end
  attr_reader :display_name, :path
end

class ScriptMate
  @@matename = "ScriptMate" # eg. RubyMate, PyMate, PerlMate...
  @@langname = "LanguageName" # eg. Python, Ruby, Perl...
  def initialize(script)
    @error = ""
    STDOUT.sync = true
    @script = script
  end
  def emit_html
    puts html_head(:window_title => "#{@script.display_name}#{@@matename}", :page_title => "#{@@matename}", :sub_title => "#{@@langname}")
    puts <<-HTML
      <div class="#{@@matename.downcase}">
    
        <div><!-- first box containing version info and script output -->
          <pre><strong>#{@@matename} r#{$SCRIPTMATE_VERSION[/\d+/]} running #{@script.version_string}</strong>
    <strong>>>> #{@script.display_name}</strong>

    <div style="white-space: normal; -khtml-nbsp-mode: space; -khtml-line-break: after-white-space;"> <!-- Script output -->
    HTML

    stdout, stderr, stack_dump = @script.run
    descriptors = [ stdout, stderr, stack_dump ]

    descriptors.each { |fd| fd.fcntl(Fcntl::F_SETFL, Fcntl::O_NONBLOCK) }
    until descriptors.empty?
      select(descriptors).shift.each do |io|
        str = io.read
        if str.to_s.empty? then
          descriptors.delete io
          io.close
        elsif io == stdout then
          print htmlize(str)
        elsif io == stderr then
          print "<span style='color: red'>#{htmlize str}</span>"
        elsif io == stack_dump then
          error << str
        end
      end
    end

    puts '</div></pre></div>'
    puts @error
    puts '<div id="exception_report" class="framed">Program exited.</div>'
    puts '</div>'
    puts '</body></html>'
  end
end