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