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 = %{ Moep
Items in Queue
#{@queue.length}
Items in ReQ
#{@requeue.length}
Workers
#{@threads.select{|t| t[:working] }.length}/#{@threads.length} working (#{@threads.select(&:alive?).length} alive)
Threads
#{Thread.list.length}
Processed entries
#{@processed}
Watching since
#{@boot}
Last draw
#{Time.current}

Latest errors


                
              
            }
            sync { Kernel.puts output }
          end

          def platypus_update_html
            dead = @threads.reject(&:alive?).length
            ti = " (#{dead} DEAD)" if dead > 0
            output = %{
              
            }
            sync { Kernel.puts output }
          end

          platypus_init_html
          @platypus_status_thread = Thread.new do
            Thread.current.abort_on_exception = true
            loop do
              platypus_update_html
              sleep opts[:draw_delay]
            end
          end
          hook :wm_shutdown do
            @platypus_status_thread.try(:kill).try(:join)
          end
        end
      end
    end
  end
end