I’m trying to get the start of the line based on the current cursor position.
Since I couldn’t find a function that can do that, I tried to write my own based on a simple text search.
Now, I think string.match is not implemented the same way as Lua itself is. When I try to run it in an online REPL, it seems to return the index of the last newline character: 43awf9z3a - Lua - OneCompiler
function getLastNewlineIndex(text, pos)
-- Ensure the position is within the bounds of the text
if pos < 1 or pos > #text then
return nil, "Position out of bounds"
end
-- Find the position of the last newline character before the cursor
local lastNewline = text:sub(1, pos):match(".*()\n")
if lastNewline then
return lastNewline - 1
else
return nil, "No newline found before the cursor"
end
end
-- Example usage
local text = "Hello, world!\nThis is a test.\nLua scripting is fun!"
local pos = #text - 1
local lastNewlineIndex = getLastNewlineIndex(text, pos)
print("The index of the last newline is:", lastNewlineIndex)
But when I run it in space-lua, I’m just getting an empty string.
My hunch is that the special case of an empty match group returning the index is not implemented.
All the Lua pattern matching stuff is a pain in the ass to be honest. The implementation is largely AI generated and it seems to be buggy still. I’m thinking what to do here. It would be good to be fully Lua compatible and support the Lua pattern language, because then people can find code elsewhere and just reuse it. Another approach would be to wrap the JS native regular expression API (more powerful) for regular expressions and suggest people use that.
I think the issue here isn’t necessarily with (the power of) the underlying RegEx engine, just the rather odd behavior of match to sometimes return a string (the match) and sometimes to return the position of the match.
It would be really nice if the behavior is identical to that of the (current) standard Lua runtime. Otherwise, we really must document the differences.
As a newcomer to Lua, I initially thought I was doing something wrong before even considering it might be the SB Lua interpreter (as in, the way SB interprets Lua) acting differently.
Technically it’s not the Lua interpreter, just my (poor) implementation of Lua’s standard library. But yeah, this is a new “opportunity” for bugs since I’m not using the official Lua implementation.
How many varieties of RegEx are there? Too many in my Opinion. The wide number of varieties introduce variations in the results of one RegEx expression… Personally, I try to stick to one version of RegEx to avoid such issues. RegEx is tricky enough already without introducing even more headaches.
I’m more in favor of sticking as close to Lua’s implementation as possible. The possibility of simply introducing a script from another source without having to make too many changes appeals to me. However, I have no idea how difficult doing something like that would be in Silverbullet’s code base. So, it is really up to you since you would have to implement it. This is just my two cents worth. LOL
it would be really nice if the behavior is identical to that of the (current) standard Lua runtime.
SilverBullet itself is not a good place to test your Lua code. You want to do it in the interpreter (Lua CLI, in my case) and just use it in SilverBullet. It’s OK to be limited to the Lua standard library functions only but these should provide the same result in both Lua and SilverBullet’s Lua. Especially the string pattern matching is the core and killer feature of the Lua standard libraries and you can not write many things without it easily (e.g. any kind of reasonably simple implementation of helper functions to parse something).
Off Topic:@zef Just few curious questions: what LLM do you use for the code eneration? And, does it do what you want? What kind of prompting techniques - in general - suites you well? Because I almost always fail to force any LLM to produce correct, valid code. I tried all of the commercial huge LLMs and all are doing similar mistakes after few iterations on the problem, they all have issues with off-by-one mistakes etc. (I tried many prompting techniques, starting from simple, to large structured and well-written prompts with examples etc., and tricks, without any real success, and I always end up in writting the code myself in shorter time than I would needed to prime the things to write what I want).
For now, I solved the original issue of this post with the following script:
function searchBackwards(pattern)
local pos = editor.getCursor ()
-- get only the text before the cursor
local pageText = editor.getText():sub(1, pos)
-- set some defaults to initialize the search
-- if they are still both 0 by the end, we know no newline was found.
local matchStart, matchEnd = 0, 0
local searchPos = pos
while matchStart < 1 and searchPos > 0 do
-- move the virtual cursor one space to the front
searchPos = searchPos - 1
-- starting from the new position, check if we can find a newline
matchStart, matchEnd = pageText:find(pattern, searchPos)
end
return matchStart, matchEnd
end
local closestPreviousNewline = searchBackwards("\n")
This iteratively checks for a newline between the start of the page and the current cursor position by slowly moving a virtual cursor to the left and checking if it can find a newline from there.
@zef The trick to let it write tests first seems intersting. I always want tests but as a part of the main prompt. Thanks for a good tip. There are certainly issues with learning data, tokenizers, stemmers. Because programming languages need very special treatments, IMHO, and these LLMs are too general and fail if the loops containing too much of uncertainty. At least, it feels like that to me. But I’ve just started to explore LLMs more. They are improving certainly, so maybe in a year or two the results will be perfect.