module WatchmonkeyCli JS_ESCAPE_MAP = { '\\' => '\\\\', '' => '<\/', "\r\n" => '\n', "\n" => '\n', "\r" => '\n', '"' => '\\"', "'" => "\\'" } class Platypus class SilentOutput def print *a end def puts *a end def warn *a end end def self.hook!(app, opts = {}) opts = opts.reverse_merge(notifications: 1, progress: true, html: false, draw_delay: 1) opts[:progress] = false if opts[:html] app.instance_eval do @platypus_status_cache = { errors: [], } # send errors via notification center hook :result_dump do |robj, args, checker| if robj.error? robj.messages.each do |m| msg = "#{robj.args[0].try(:name) || robj.args[0].presence || "?"}: #{m}" @platypus_status_cache[:errors].unshift([Time.current, msg]) @platypus_status_cache[:errors].pop if @platypus_status_cache[:errors].length > 20 case opts[:notifications] when 1 # makes no sound fmsg = msg.gsub('"', '\"').gsub("'", %{'"'"'}) `osascript -e 'display notification "#{fmsg}" with title "WatchMonkey"'` when 2 # makes a sound puts "NOTIFICATION:#{msg}" end end end end if opts[:notifications] hook :wm_work_start, :wm_work_end do # mastermind calculation I swear :D (<-- no idea what I did here) # puts "PROGRESS:#{((@threads.length-@threads.select{|t| t[:working] }.length.to_d) / @threads.length * 100).to_i}" sync do active = @threads.select{|t| t[:working] }.length total = @threads.select{|t| t[:working] }.length + @queue.length perc = total.zero? ? 100 : (active.to_d / total * 100).to_i puts "PROGRESS:#{perc}" end end if opts[:progress] # HTML output (fancy as fuck!) if opts[:html] @opts[:stdout] = SilentOutput.new def escape_javascript str str.gsub(/(\|<\/|\r\n|\342\200\250|\342\200\251|[\n\r"'])/u) {|match| JS_ESCAPE_MAP[match] } end def platypus_init_html output = %{