Module: Rvim::Lua::Loop

Defined in:
lib/rvim/lua/loop.rb

Overview

vim.loop / vim.uv — minimal libuv shim.

Real libuv is an async event loop. We don’t have one. What v3.12 ships:

- vim.loop.new_timer():start(timeout_ms, repeat_ms, cb) /:stop() /:close()
- vim.defer_fn(fn, ms)  (sugar for one-shot timer)
- vim.schedule(fn)       (run on next pump — ms=0 timer)
- vim.loop.now()         (monotonic-ish)
- vim.loop.hrtime()

Timers fire when Editor#pump_lua_loop is called. The render loop in Editor.start should call it once per iteration; for headless use (tests, scripts), callers pump manually.

Defined Under Namespace

Classes: Scheduler, Timer

Class Method Summary collapse

Class Method Details

.install(state, editor, _runtime) ⇒ Object



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/rvim/lua/loop.rb', line 83

def install(state, editor, _runtime)
  scheduler = Scheduler.new
  editor.instance_variable_set(:@lua_scheduler, scheduler)

  state.function('_rvim_loop_new_timer') { Object.new } # placeholder; the Lua side wraps via metatable below
  state.function '_rvim_loop_timer_start' do |timeout_ms, repeat_ms, cb|
    scheduler.add(timeout_ms.to_f, repeat_ms.to_f, cb)
  end
  state.function('_rvim_loop_timer_stop')  { |id| scheduler.stop(id.to_i) }
  state.function('_rvim_loop_timer_close') { |id| scheduler.close(id.to_i) }
  state.function('_rvim_loop_now')         { (Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1000).to_i }
  state.function('_rvim_loop_hrtime')      { (Process.clock_gettime(Process::CLOCK_MONOTONIC) * 1_000_000_000).to_i }

  state.eval(<<~LUA)
    vim.loop = vim.loop or {}

    local function make_timer()
      local self = { _id = nil }
      function self:start(timeout, rep, cb)
        self._id = _rvim_loop_timer_start(timeout, rep, cb)
      end
      function self:stop()
        if self._id then _rvim_loop_timer_stop(self._id) end
      end
      function self:close()
        if self._id then _rvim_loop_timer_close(self._id); self._id = nil end
      end
      return self
    end

    vim.loop.new_timer = make_timer
    vim.loop.now    = _rvim_loop_now
    vim.loop.hrtime = _rvim_loop_hrtime

    vim.uv = vim.loop  -- modern alias

    function vim.defer_fn(fn, ms)
      local t = vim.loop.new_timer()
      t:start(ms or 0, 0, function()
        fn()
        t:close()
      end)
    end

    function vim.schedule(fn)
      vim.defer_fn(fn, 0)
    end
  LUA
end