Why Lua is cool

Not production ready but here’s the essence of the Git plug reimplemented in Lua:

```space-lua
git = {}

function git.commit(message)
  message = message or "Snapshot"
  print "Comitting..."
  shell.run("git", {"add", "./*"})
  shell.run("git", {"commit", "-a", "-m", message})
end

function git.sync()
  git.commit()
  print "Pulling..."
  shell.run("git", {"pull"})
  print "Pushing..."
  shell.run("git", {"push"})
end

command.define {
  name = "Git: Commit",
  run = function()
    local message = editor.prompt "Commit message:"
    git.commit(message)
  end
}

command.define {
  name = "Git: Sync",
  run = function()
    git.sync()
    editor.flashNotification "Done!"
  end
}
```

Isn’t that beautiful? (The answer is “Yes”)

6 Likes

Will the Lua support eventually have a way to do the autocommit portion every 5 mins as well? Is there some sort of internal timer event that the Lua code could add a listener for?

Yeah, this is next on my list for exactly this use case :wink: I have to figure out an API for this.

1 Like

What do you think about simply having a cron:second event that triggers every second (obviously)? It’s then possible to build fancier abstractions on top of that (like a proper cron scheduler).

Ah, the beautiful Lua…

saved me the headache trying to understand the obscure javascript syntax. Another neovim user arrives at his comfort zone. :partying_face:

1 Like

This stuff will only make it to the v2 branch, but:

local secondsPassed = 0
event.listen {
  name = "cron:secondPassed",
  run = function()
    secondsPassed = secondsPassed + 1
    if secondsPassed % 60 == 20 then
      print "Comittin' time"
      git.sync()
    end
  end
}

Sounds good. Seems secondsPassed could grow to some large number if one doesn’t ‘System: Reload’ or reindex from time to time but maybe that is a non-issue.

Well that was just an example. You can always reset the counter every minute :laughing:

Duh. Should have thought of that :slight_smile:

You could also just look at the local time and see if it’s a multiple of x :slight_smile:

Why keep a timer if you already have a clock :smiley: Unless the time since first load is important of course. But then you could also just store that and subtract it from the clock.

It is pretty cool, I was able to whip up a quick “stream llm chat to editor” lua script with working streaming.

local openaiLib = js.import("https://esm.sh/[email protected]")
local openaiClient = js.new(openaiLib.OpenAI, {apiKey=apiKey, dangerouslyAllowBrowser=true})

function streamCompletionIntoEditor2(messages)
  local startPos = string.len(editor.getText())
  local resp = openaiClient.chat.completions.create({
    model = "gpt-4o",
    stream = true,
    messages = js.tojs(messages)})
  local fullResponse = "\n**Assistant**: "
  editor.insertAtPos(fullResponse, startPos)
  for value in js.eachIterable(resp) do
    local newDelta = value.choices[1].delta.content
    if newDelta ~= "" and newDelta ~= nil then
      editor.insertAtPos(newDelta, startPos + string.len(fullResponse))
      fullResponse = fullResponse + newDelta
    end
  end
  editor.insertAtPos("\n**User**: ", startPos + string.len(fullResponse))
  editor.moveCursor(startPos + string.len(fullResponse) + string.len("\n**User**: "), true)
end

Definitely missing features (and cheating by using an external lib), but I wasn’t expecting it to be so easy either :slight_smile:

@justyns I have been building something very similar as a toy thing to stress test Lua. Will share it later. I also implemented (streaming chat) and a few other nice things.

2 Likes

Ok, finally posted it: silverbullet-assistant.md · GitHub

Still very much WIP but you get the idea.

1 Like

I’m a little late to the party, but maybe there could be an API callback function

function setCallback(who: function, when: number)

Sort of thing? The every 5 minute function could be a simple:

  1. Call git.sync
  2. Call setCallback(me, 60*5)

This would effectively be the same as listening to the cron:secondPassed event (which now exists on v2) and doing a little math on it, right?

Assuming that listening to cron:secondPassed causes a callback every second, no I was thinking more of SilverBullet’s plug manager or someone having a list of who wants to be called and when, allowing for just one callback that runs every second instead of one per plug.

But I guess my idea trades off fewer per second function calls for a single point of failure.

And that’s assuming I’ve not wildly misunderstood cron:secondPassed’s behaviour

First thanks for silvrbullet I really like :smiley:
One question about the event, what happens when I close silverbullet, the events are launching while is closed? or is only working when the client is open?

I was want to do something that is launched in cron when silverbullet is closed.
I wanted to do:
Each morning read a list of objects generate a promt feed to an AI and sent a email/telebran bot message or something like that.

Thanks

Events only trigger when the client is open and active (browsers even stop scheduling events, or at least delay them when a tab or window isn’t active). At least this is how it works in Sync mode and in v2, no real way around that. In v1, since Lua code also runs on the server, your client doesn’t need to be active.

I thought so, thanks a lot anyway