lib/guard/livereload/reactor.rb
require 'multi_json'
module Guard
class LiveReload < Plugin
class Reactor
attr_reader :web_sockets, :thread, :options, :connections_count
def initialize(options)
@web_sockets = []
@options = options
@thread = Thread.new { _start_reactor }
@connections_count = 0
end
def stop
thread.kill
end
def reload_browser(paths = [])
msg = "Reloading browser: #{paths.join(' ')}"
Compat::UI.info msg
if options[:notify]
Compat::UI.notify(msg, title: 'Reloading browser', image: :success)
end
paths.each do |path|
data = _data(path)
Compat::UI.debug(data)
web_sockets.each { |ws| ws.send(MultiJson.encode(data)) }
end
end
private
def _data(path)
data = {
command: 'reload',
path: "#{Dir.pwd}/#{path}",
liveCSS: options[:apply_css_live]
}
if options[:override_url] && File.exist?(path)
data[:overrideURL] = '/' + path
end
data
end
def _start_reactor
EventMachine.epoll if EventMachine.epoll?
EventMachine.kqueue if EventMachine.kqueue?
EventMachine.run do
EventMachine.start_server(
options[:host],
options[:port],
WebSocket,
options
) do |ws|
ws.onopen { _connect(ws) }
ws.onclose { _disconnect(ws) }
ws.onmessage { |msg| _print_message(msg) }
end
Compat::UI.info 'LiveReload is waiting for a browser to connect.'
end
end
def _connect(ws)
@connections_count += 1
Compat::UI.info 'Browser connected.' if connections_count == 1
ws.send MultiJson.encode(
command: 'hello',
protocols: ['http://livereload.com/protocols/official-7'],
serverName: 'guard-livereload'
)
@web_sockets << ws
rescue
Compat::UI.error $ERROR_INFO
Compat::UI.error $ERROR_INFO.backtrace
end
def _disconnect(ws)
@web_sockets.delete(ws)
end
def _print_message(message)
message = MultiJson.decode(message)
Compat::UI.info "Browser URL: #{message['url']}" if message['command'] == 'url'
end
end
end
end