class RubyBug
    def initialize(proc)
        @proc = proc;
        @lline, @lfile, @bk, @gotoBk, @values, @files, @brkPts = 
            nil, nil, nil, nil, Array.new(), Hash.new(), Hash.new();
    end
    
    def trace(*values)
        @values = values;
    end

    def breakPoints(points)
        @brkPts = points;
    end

    def justRun()
        @proc.call();
    end

    def start()
        @lline, @lfile, @bk, @gotoBk = nil, nil, nil, nil;
        set_trace_func(Proc.new{ |ntn1, file, line, ntn2, binding, name|
            break if (@lline == line and @lfile == file);
            @lline, @lfile = line, file;
            unless (@files.has_key?(file))
                @files[file] = File.open(file).readlines.each{|l| l.chomp!};
            end
            break if ((@bkline and @bkline != line) or
                (@bkfile and not file =~ /#{@bkfile}/));
            break if (@gotoBk and (not @brkPts.has_key?(file) or 
                    not @brkPts[file].include?(line)));

            puts '########################################';
            puts "FILE: #{file},  LINE: #{line}";
            puts "    "+@files[file][line-1];
            around = (@values & (eval("local_variables | " +
                "self.instance_variables",binding))).compact;
            if (not around.empty?)
                print "Tracing:\n    ";
                puts around.map!{|v|
                    val = eval(v,binding);
                    v+":    "+(val ? val.to_s : '')
                }.join("\n    ");
            end
            puts '----------------------------------------';

            print "Go Anywhere?: ";
            action = gets.strip;

            if (action.empty?)
                @bkfile, @bkline, @gotoBk = nil, nil, nil;
            elsif (action == "n")
                @bkfile, @bkline, @gotoBk = nil, nil, true;
            elsif (action == "s")
                @bkfile, @bkline, @gotoBk = file, line+1, nil;
                @bkline += 1 while (@files[file][@bkline+1].empty?);
            elsif (action.to_i > 0)
                @gotoBk, @bkline = nil, action.to_i;
            else (action.to_i == 0)
                @gotoBk, @bkfile = nil, action;
                print "What line?: ";
                bkl = gets.strip;
                @bkline = bkl.empty? ? nil : bkl.to_i;
            end
        });
        @proc.call();
    end
end