class Textbringer::GhostText::Server

Public Instance Methods

call(env) click to toggle source
# File lib/textbringer/ghost_text/server.rb, line 13
def call(env)
  if Faye::WebSocket.websocket?(env)
    accept_client(env)
  else
    json = {
      "WebSocketPort" => CONFIG[:ghost_text_port],
      "ProtocolVersion" => 1
    }.to_json
    [200, {'Content-Type' => 'application/json'}, [json]]
  end
end

Private Instance Methods

accept_client(env) click to toggle source
# File lib/textbringer/ghost_text/server.rb, line 27
def accept_client(env)
  ws = Faye::WebSocket.new(env, nil,
                           ping: CONFIG[:ghost_text_ping_interval])
  next_tick! do
    setup_buffer(ws)
  end
  ws.rack_response
end
setup_buffer(ws) click to toggle source
# File lib/textbringer/ghost_text/server.rb, line 36
def setup_buffer(ws)
  buffer = Buffer.new_buffer("*GhostText*")
  switch_to_buffer(buffer)

  syncing_from_remote_text = false

  ws.on :message do |event|
    data = JSON.parse(event.data)
    next_tick do
      syncing_from_remote_text = true
      begin
        buffer.replace(data["text"])
        if pos = data["selections"]&.dig(0, "start")
          byte_pos = data["text"][0, pos].bytesize
          buffer.goto_char(byte_pos)
        end
      ensure
        syncing_from_remote_text = false
      end
      if (title = data['title']) && !title.empty?
        buffer.name = "*GhostText:#{title}*"
      end
      switch_to_buffer(buffer)
    end
  end

  ws.on :close do |event|
    ws = nil
    next_tick do
      kill_buffer(buffer, force: true)
    end
  end

  buffer.on :modified do
    unless syncing_from_remote_text
      pos = buffer.substring(0, buffer.point).size
      data = {
        "text" => buffer.to_s,
        "selections" => [{ "start" => pos, "end" => pos }]
      }
      ws&.send(data.to_json)
    end
  end

  buffer.on :killed do
    ws&.close
  end
end