class Neovim::Session
Wraps an event loop in a synchronous API using +Fiber+s.
@api private
Attributes
request_id[W]
Public Class Methods
new(event_loop)
click to toggle source
# File lib/neovim/session.rb, line 21 def initialize(event_loop) @event_loop = event_loop @main_thread = Thread.current @main_fiber = Fiber.current @response_handlers = Hash.new(-> {}) @pending_messages = [] @request_id = 0 end
Public Instance Methods
next()
click to toggle source
# File lib/neovim/session.rb, line 40 def next return @pending_messages.shift if @pending_messages.any? run { |msg| stop; msg } end
notify(method, *args)
click to toggle source
# File lib/neovim/session.rb, line 83 def notify(method, *args) @event_loop.notify(method, *args) end
request(method, *args)
click to toggle source
Make an RPC request and return its response.
If this method is called inside a callback, we are already inside a Fiber handler. In that case, we write to the stream and yield the Fiber. Once the response is received, resume the Fiber and return the result.
If this method is called outside a callback, write to the stream and run the event loop until a response is received. Messages received in the meantime are enqueued to be handled later.
# File lib/neovim/session.rb, line 56 def request(method, *args) main_thread_only do @request_id += 1 blocking = Fiber.current == @main_fiber log(:debug) do { method_name: method, request_id: @request_id, blocking: blocking, arguments: args } end @event_loop.request(@request_id, method, *args) response = blocking ? blocking_response : yielding_response raise(Disconnected) if response.nil? raise(response.error) if response.error response.value end end
respond(request_id, value, error=nil)
click to toggle source
# File lib/neovim/session.rb, line 79 def respond(request_id, value, error=nil) @event_loop.respond(request_id, value, error) end
run(&block)
click to toggle source
# File lib/neovim/session.rb, line 30 def run(&block) block ||= ->(msg) { @pending_messages << msg } @running = true @event_loop.run do |message| Fiber.new { message.received(@response_handlers, &block) }.resume end end
shutdown()
click to toggle source
# File lib/neovim/session.rb, line 87 def shutdown @running = false @event_loop.shutdown end
stop()
click to toggle source
# File lib/neovim/session.rb, line 92 def stop @running = false @event_loop.stop end
Private Instance Methods
blocking_response()
click to toggle source
# File lib/neovim/session.rb, line 99 def blocking_response @response_handlers[@request_id] = ->(res) { stop; res } run end
main_thread_only() { || ... }
click to toggle source
# File lib/neovim/session.rb, line 110 def main_thread_only if Thread.current == @main_thread yield if block_given? else raise( "A Ruby plugin attempted to call neovim outside of the main thread, " \ "which is not yet supported by the neovim gem." ) end end
yielding_response()
click to toggle source
# File lib/neovim/session.rb, line 104 def yielding_response fiber = Fiber.current @response_handlers[@request_id] = ->(response) { fiber.resume(response) } Fiber.yield end