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”)

7 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?

1 Like

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

2 Likes

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).

1 Like

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:

2 Likes

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
}

1 Like

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.

1 Like

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

1 Like

Duh. Should have thought of that :slight_smile:

1 Like

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.

1 Like

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:

1 Like

@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.

3 Likes

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

Still very much WIP but you get the idea.

4 Likes

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)
1 Like

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?

1 Like

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

1 Like

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

1 Like

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.

1 Like

I thought so, thanks a lot anyway

1 Like