[LIBRARY] srt.lua A simple srt caption parser

Showcase your libraries, tools and other projects that help your fellow love users.
Post Reply
alejandroalzate
Citizen
Posts: 67
Joined: Sat May 08, 2021 9:45 pm

[LIBRARY] srt.lua A simple srt caption parser

Post by alejandroalzate »

This is my first contribution to the community and really there's not much to talk about this is a simple library for getting the current line of an .srt of a song or video in a given time.

Get a copy here:
Github: https://github.com/alejandro-alzate/srt-lua
or here:
Luarocks: https://luarocks.org/modules/alejandro-alzate/srt

Overview
There are three simple highlights to the library simple quick and dirty as well of three api methods to keep in mind:

The function srt.new(string) returns an table containing the given string, a clock and the text on the given time plus some other goodies.

A real world example would look like this:

local captions = srt.new(love.filesystem.read("captions.en.srt"))

The best way to interact with this library is with the method :setTime(time) that takes an integer time that is the time elapsed in seconds, this method also automatically calls internally :update(delta) that is only needed if you want to offset the playback of the captions. you can use the Source:tell to get the elapsed time and pass it to srt, a real world example would look like this:

captions:setTime(yourAudio:tell())

Last but not least important there's the :getText() method that just returns the text stored within the captions object this can seem useless since you can access directly to the text through captions.outputText but calling the method is recommended because it could get updates to add other functionality also i'm not gonna lie but it just looks good in my humble opinion.
Once again here could be a real world example of the library on use.

local text = captions:getText()
local x = (love.graphics.getWidth() / 2) - (love.graphics.getFont():getWidth(text) / 2 )
local y = love.graphics.getHeight() - love.graphics.getFont():getHeight() * 2
love.graphics.print(captions:getText(), x, y)

A complete example would look like this:
Image

Well with nothing to be said anymore i log off, have a great day/night and enjoy coding with my library!

Code: Select all

target = boardIndex.getWhosPeekingThisLine()
target:setObey(true)
User avatar
dusoft
Party member
Posts: 654
Joined: Fri Nov 08, 2013 12:07 am
Location: Europe usually
Contact:

Re: [LIBRARY] srt.lua A simple srt caption parser

Post by dusoft »

Nice. Are you developing a video player?
RNavega
Party member
Posts: 385
Joined: Sun Aug 16, 2020 1:28 pm

Re: [LIBRARY] srt.lua A simple srt caption parser

Post by RNavega »

Hi Alejandro, congratulations on getting it done. I always learn a lot when I finish a project, I'm sure it must've been the same for you.

With that said, I don't think it's quite production-quality yet. There's room for a lot of optimizations.
For example, reading your code, the update(delta) method parses the entire SRT file on each call. When you call it from love.update() like in your usage notes, that means it's being run per frame on 60FPS or at least 30FPS. That's a lot of redundant work.
You need to cache the structures you're creating when parsing so you can reuse them later.

Another thing is, making it faster to sample what's the current subtitle to display given the current seek time.
Seeking will always involve some sort of looping (like a binary search etc) since there's no easy way to hash the start time and end time of a subtitle in a way that lets you just specify the time and have it spit out the appropriate subtitle. This is the same challenge that keyframed animations have, with animation code having to locate what's the current keyframe to use based on the animation seek time.
However, in both cases for keyframes and subtitles, you can optimize things based on the fact that, for most of the time, you're usually advancing forward in time, so you only need to keep track of the current subtitle and when the time advances past its end time, you can iterate from that subtitle onward until you find the next one whose end time is ahead of the current seek time. This makes it cheap to query the current subtitle text to display.
Seeking backwards is very rare, like only when the user rewinds to some previous point or something like that, so it's okay if it's done with a brute-force loop.

I took a bit of time to rewrite it with those optimizations in mind.

Code: Select all

-- Code by Rafael Navega (2024)
-- License: Public Domain


-- Allow 'srt' to be used as a metatable for instances of subtitles objects.
local srt = {}
srt.__index = srt


-- The 'msDT' time offset should be in MILLISECONDS.
--
-- To be called from love.update() like so:
-- mySubtitle:advance(dt * 1000)
--
-- Returns true if the index of the node being sampled has changed, or false if it hasn't.
function srt:advance(msDT)
    local newTime = self.time + msDT
    self.time = newTime
    -- Check if we need to advance to a future node whose *end time* is ahead of
    -- the current seek time.
    local newIndex = self.currentIndex or 1
    local node = self.parsedNodes[newIndex]
    while node and newTime > node.endTime do
        newIndex = newIndex + 1
        node = self.parsedNodes[newIndex]
    end
    if self.currentIndex ~= newIndex then
        if newIndex > self.lastIndex then
            self.currentIndex = self.lastIndex
        else
            self.currentIndex = newIndex
        end
        return true
    end
    return false
end


-- The 'msDT' time offset should be in MILLISECONDS.
function srt:rewind(msDT)
    local newTime = self.time - msDT
    self.time = newTime
    -- Check if we need to rewind to a previous node whose *start time* is behind
    -- the current seek time.
    local newIndex = self.currentIndex or self.lastIndex
    local node = self.parsedNodes[newIndex]
    while node and newTime < node.startTime do
        newIndex = newIndex - 1
        node = self.parsedNodes[newIndex]
    end
    if self.currentIndex ~= newIndex then
        if newIndex < 1 then
            self.currentIndex = 1
        else
            self.currentIndex = newIndex
        end
        return true
    end
    return false
end


function srt:getText()
    local node = self:getNode()
    return (node and node.text or nil)
end


function srt:getNode()
    local node = self.parsedNodes[self.currentIndex]
    if node and self.time >= node.startTime and self.time <= node.endTime then
        return node
    else
        return nil
    end
end


function srt:getTime()
    return self.time
end


-- The absolute 'msTime' should be in MILLISECONDS.
function srt:setTime(msTime)
    self.time = msTime
    -- Seek from the beginning until we find some near node, like the next
    -- node whose end time is bigger than 'msTime'.
    for index = 1, self.lastIndex do
        if self.parsedNodes[index].endTime > msTime then
            self.currentIndex = index
            return
        end
    end
end


function srt:clear()
    -- Note: when on LuaJIT, there's a special method for the fast clearing of tables.
    -- require('table.clear')
    -- (...)
    -- table.clear(self.parsedNodes)
    -- Read more in here: https://luajit.org/extensions.html
    for index = 1, self.lastIndex do
        self.parsedNodes[index] = nil
    end
    self.lastIndex = 0
end



function srt:parse(srtString)
    self:clear()
    local nodeCount = 0
    -- Make sure that the input text finishes with the SRT blank line separator ('\n\n'), so
    -- that the last subtitle piece is definitely read. If the file already ends on that separator
    -- then this won't affect anything.
    srtString = srtString .. '\n\n'
    -- SRT format from: https://en.wikipedia.org/wiki/SubRip#Format
    -- Note: added a safeguard in case the SRT file is "extended" with coordinates
    -- after the timestamps, in the same line.
    for srtIndex, hours1, minutes1, seconds1, millis1,
        hours2, minutes2, seconds2, millis2, text in srtString:gmatch(
        '(%d+)\n'..
        '(%d%d):(%d%d):(%d%d),(%d%d%d) %-%-> (%d%d):(%d%d):(%d%d),(%d%d%d)[^\n]*\n'..
        '(.-)\n'..
        '\n') do
        -- Create a new node.
        nodeCount = nodeCount + 1
        local newNode = {
            -- Transform the timecodes into milliseconds integers, easier to compare.
            -- Note: strings are being implicitly coerced into numbers.
            startTime = hours1 * 3600000 + minutes1 * 60000 + seconds1 * 1000 + millis1,
            endTime = hours2 * 3600000 + minutes2 * 60000 + seconds2 * 1000 + millis2,
            index = nodeCount,
            text = text
        }
        table.insert(self.parsedNodes, newNode)
    end
    -- Reset the subtitle scanning to read from the first node.
    self.time = 0.0
    self.currentIndex = (nodeCount > 0 and 1 or nil)
    self.lastIndex = nodeCount
end


-- Used to create new instances of a subtitle object that parsed a piece of text.
-- To be used like so:
-- local mySubtitle = srt.new(myString)
function srt.new(srtString)
    -- Apply 'srt' as the metatable to a new blank table, so all shared functions and
    -- shared variables are available.
    local subs = setmetatable({time=0.0, parsedNodes={}, lastIndex=0}, srt)
    if srtString and type(srtString) == 'string' then
        subs:parse(tostring(srtString))
    end
    return subs
end


function tests()
    local testString=[[1
00:02:16,612 --> 00:02:19,376
Senator, we're making
our final approach into Coruscant.

2
00:02:19,482 --> 00:02:21,609
Very good, Lieutenant.

3
00:03:13,336 --> 00:03:15,167
We made it.

4
00:03:18,608 --> 00:03:20,371
I guess I was wrong.

5
00:03:20,476 --> 00:03:22,671
There was no danger at all.]]
    local mySubtitle = srt.new(testString)
    for index = 1, mySubtitle.lastIndex do
        local node = mySubtitle.parsedNodes[index]
        print(node.index)
        print(node.startTime, node.endTime)
        print(node.text)
        print()
    end
    print('-----------')
    -- Should be nil (time hasn't yet reached the first node, at 02:16.612)
    print('Current time:', mySubtitle.time, 'Text:', mySubtitle:getText())

    -- Test advancing 2 minutes and twenty seconds, in milliseconds.
    -- This should sample subtitle node #2, that ranges 02:19.482 ~ 02:21.609.
    print('Advancing...')
    mySubtitle:advance((2*60 + 20) * 1000)
    print('Current time:', mySubtitle.time, 'Text:', mySubtitle:getText())

    -- Test seeking and rewinding.
    -- This should sample subtitle node #4, that ranges 03:18.608 ~ 03:20.371.
    print('Seeking & rewinding...')
    mySubtitle:setTime((3 * 60 + 22) * 1000)
    mySubtitle:rewind(3000)
    print('Current time:', mySubtitle.time, 'Text:', mySubtitle:getText())
end


-- Optional, run the tests function and print to console.
--tests()

return srt
Good luck with your future projects.

Edit 4: Fixed some cases when the index counter could turn nil and stay there.
Last edited by RNavega on Tue Feb 06, 2024 4:32 am, edited 2 times in total.
alejandroalzate
Citizen
Posts: 67
Joined: Sat May 08, 2021 9:45 pm

Re: [LIBRARY] srt.lua A simple srt caption parser

Post by alejandroalzate »

RNavega wrote: Thu Jan 11, 2024 1:57 am Hi Alejandro, congratulations on getting it done. I always learn a lot when I finish a project, I'm sure it must've been the same for you.

With that said, I don't think it's quite production-quality yet. There's room for a lot of optimizations.
For example, reading your code, the update(delta) method parses the entire SRT file on each call. When you call it from love.update() like in your usage notes, that means it's being run per frame on 60FPS or at least 30FPS. That's a lot of redundant work.
You need to cache the structures you're creating when parsing so you can reuse them later.

Another thing is, making it faster to sample what's the current subtitle to display given the current seek time.
Seeking will always involve some sort of looping (like a binary search etc) since there's no easy way to hash the start time and end time of a subtitle in a way that lets you just specify the time and have it spit out the appropriate subtitle. This is the same challenge that keyframed animations have, with animation code having to locate what's the current keyframe to use based on the animation seek time.
However, in both cases for keyframes and subtitles, you can optimize things based on the fact that, for most of the time, you're usually advancing forward in time, so you only need to keep track of the current subtitle and when the time advances past its end time, you can iterate from that subtitle onward until you find the next one whose end time is ahead of the current seek time. This makes it cheap to query the current subtitle text to display.
Seeking backwards is very rare, like only when the user rewinds to some previous point or something like that, so it's okay if it's done with a brute-force loop.

I took a bit of time to rewrite it with those optimizations in mind.

Code: Select all

-- Allow 'srt' to be used as a metatable for instances of subtitles objects.
local srt = {}
srt.__index = srt


-- The 'msDT' time offset should be in MILLISECONDS.
--
-- To be called from love.update() like so:
-- mySubtitle:advance(dt * 1000)
function srt:advance(msDT)
    self.time = self.time + msDT
    -- Check if we need to advance to a future node whose end time is ahead of
    -- the current seek time.
    if self.currentNode and self.time > self.currentNode.endTime then
        local currentIndex = self.currentNode.index
        local node = self.currentNode
        while node and self.time > node.endTime do
            currentIndex = currentIndex + 1
            node = self.parsedNodes[currentIndex]
        end
        if self.currentNode ~= node then
            self.currentNode = node
            return true
        end
    end
    return false
end


function srt:getText()
    if self.currentNode and self.time >= self.currentNode.startTime then
        return self.currentNode.text
    else
        return nil
    end
end


function srt:getTime()
	return self.time
end


-- The absolute 'msTime' should be in MILLISECONDS.
function srt:setTime(msTime)
	self.time = msTime
    -- Seek until we find the next subtitle node whose end time is bigger than 'time'.
    for index = 1, #self.parsedNodes do
        local node = self.parsedNodes[index]
        if node.endTime > msTime then
            self.currentNode = node
            return
        end
    end
end


function srt:clear()
    -- Note: when on LuaJIT, there's a special method for the fast clearing of tables.
    -- require('table.clear')
    -- (...)
    -- table.clear(self.parsedNodes)
    -- Read more here: https://luajit.org/extensions.html
    for index = 1, #self.parsedNodes do
        self.parsedNodes[index] = nil
    end
    self.currentNode = nil
end



function srt:parse(srtString)
    self:clear()
    local nodeCount = 0
    -- Make sure that the input text finishes with the SRT blank line separator ('\n\n'), so
    -- that the last subtitle piece is definitely read. If the file already ends on that separator
    -- then this won't affect anything.
    srtString = srtString .. '\n\n'
    -- SRT format from: https://en.wikipedia.org/wiki/SubRip#Format
    for srtIndex, hours1, minutes1, seconds1, millis1,
        hours2, minutes2, seconds2, millis2, text in srtString:gmatch(
        '(%d+)\n'..
        '(%d%d):(%d%d):(%d%d),(%d%d%d) %-%-> (%d%d):(%d%d):(%d%d),(%d%d%d)\n'..
        '(.-)\n'..
        '\n') do
        -- Create a new node.
        nodeCount = nodeCount + 1
        local newNode = {
            -- Transform the timecodes into milliseconds integers, easier to compare.
            -- Note: strings are being implicitly coerced into numbers.
            startTime = hours1 * 3600000 + minutes1 * 60000 + seconds1 * 1000 + millis1,
            endTime = hours2 * 3600000 + minutes2 * 60000 + seconds2 * 1000 + millis2,
            index = nodeCount,
            text = text
        }
        table.insert(self.parsedNodes, newNode)
    end
    -- Reset the subtitle scanning to read from the first node.
    self.time = 0.0
    self.currentNode = self.parsedNodes[1]
end


function srt.new(srtString)
    -- Apply 'srt' as the metatable to a new blank table, so all shared functions and
    -- shared variables are available.
    local subs = setmetatable({time=0.0, parsedNodes={}, currentNode=nil}, srt)
    if srtString and type(srtString) == 'string' then
        subs:parse(tostring(srtString))
    end
    return subs
end


return srt
Good luck with your future projects.

Edit: updated the above with a better pattern that reads whole blocks at once, instead of using a state machine parser as it was before.
Edit 2: fixed a bug in srt:advance().
Thanks for the contribution i might take a deeper look and test it on my free time, my compromises were that no one had made a library for this purpose earlier and while i know a fair bit of lua code i don't consider myself a master of coding. that "a crappy implementation" written on my description i wasn't joking, this library was a "throw things on the wall to see what sticks" because i wanted a quick & dirty implementation of it up and running.
about the "Rewind is rare" in my case that is a pickle since this library was born in a game where will be dialogue playing backwards so i didn't wanted to risk it an so i just made the crappy way brute forcing the file each frame. maybe if I iterate your take of my code (once i understand it) so is resilient to go backwards and such things. i will update the code with it.
I know my O() function is garbage, but since generally even a 3hr file could get parsed in so little i took the performance hit.
Once i test it for my use cases i'll integrate it, so do you want to get credited as a contributor? if so what display name and such
I'm glad people took a peek at my lib though.

Edit: i took a look at the code and i couldn't make it work my guess is the parse method is not making parsedNodes successfully, not even converting the units (since it shall be retro compatible and most of the units passed are floats in seconds) also my brain hurts with lua's oop way of doing things, i mean i do understand it but man that mental parsing hurts so bad
Last edited by alejandroalzate on Sun Feb 04, 2024 10:54 pm, edited 4 times in total.

Code: Select all

target = boardIndex.getWhosPeekingThisLine()
target:setObey(true)
alejandroalzate
Citizen
Posts: 67
Joined: Sat May 08, 2021 9:45 pm

Re: [LIBRARY] srt.lua A simple srt caption parser

Post by alejandroalzate »

dusoft wrote: Mon Jan 08, 2024 11:45 am Nice. Are you developing a video player?
A game, it contains dialogs, voiced music and such

Code: Select all

target = boardIndex.getWhosPeekingThisLine()
target:setObey(true)
RNavega
Party member
Posts: 385
Joined: Sun Aug 16, 2020 1:28 pm

Re: [LIBRARY] srt.lua A simple srt caption parser

Post by RNavega »

alejandroalzate wrote: Sun Feb 04, 2024 7:13 pm I know my O() function is garbage, but since generally even a 3hr file could get parsed in so little i took the performance hit.
Since your code works, I don't consider it garbage. But it would be much faster using caching -- not in a noticeable way though, probably microseconds faster.
alejandroalzate wrote: Sun Feb 04, 2024 7:13 pm Once i test it for my use cases i'll integrate it, so do you want to get credited as a contributor? if so what display name and such
I'm glad people took a peek at my lib though.
Okay, I added my name and the Public Domain license, but you don't have to use it at all.
The example is functional and is how I'd do it, with those optimizations and the relative seeking (seeking from the current node onwards or backwards, instead of brute-forcing from the start or the end of the file).
alejandroalzate wrote: Sun Feb 04, 2024 7:13 pm Edit: i took a look at the code and i couldn't make it work my guess is the parse method is not making parsedNodes successfully, not even converting the units (since it shall be retro compatible and most of the units passed are floats in seconds) also my brain hurts with lua's oop way of doing things, i mean i do understand it but man that mental parsing hurts so bad
I added a tests() function that comes with the sample SRT from the Wikipedia article, please check it out.
Also note the comments, you need to pass the time as milliseconds (which is timeInSeconds * 1000).

But anyway, if you'd rather use seconds as units, you can change the code in :parse() to use seconds to be like this:

Code: Select all

        local newNode = {
            -- Transform the timestamps into seconds.
            -- Note: strings are being implicitly coerced into numbers.
            startTime = hours1 * 3600 + minutes1 * 60 + seconds1 + millis1 / 1000.0,
            endTime = hours2 * 3600 + minutes2 * 60 + seconds2 + millis2 / 1000.0,
            index = nodeCount,
            text = text
        }
And also change the tests() function to use these lines instead, that use seconds:

Code: Select all

    print('Advancing...')
    mySubtitle:advance((2*60 + 20))
    print('Current time:', mySubtitle.time, 'Text:', mySubtitle:getText())

    -- Test seeking and rewinding.
    -- This should sample subtitle node #4, that ranges 03:18.608 ~ 03:20.371.
    print('Seeking & rewinding...')
    mySubtitle:setTime((3 * 60 + 22))
    mySubtitle:rewind(3)
The rest of the code doesn't need changes, it'll work the same since it just compares the numbers and doesn't care about the units.
alejandroalzate
Citizen
Posts: 67
Joined: Sat May 08, 2021 9:45 pm

Re: [LIBRARY] srt.lua A simple srt caption parser

Post by alejandroalzate »

I swear it doesn't make parsedNodes now i'm sure using zbstudio are you doing any luaJIT shenanigans or obscure tricks as you noted on srt:clear that i'm not aware of?

I swear i followed your steps the thing is broken for me:

As you can see the console is past the srt.new()

Edit omg i'm cringing so hard rn of my blindness you version of the code cares if you call srt:new() instead of srt.new() (although i gonna take a look if i did used colon on other places)
nope the same deal:

Code: Select all

local function loadCaptions()
	--Load captions
	local srtLUT = { english = "en", spanish = "es" }
	local captionsText = ""
	local info = love.filesystem.getInfo
	local correctCaptions = info("res/sfx/songs/monster/monster." .. srtLUT[getNestedValue("config.system.language")] .. ".srt")
	local englishCaptions = info("res/sfx/songs/monster/monster.en.srt")
	local genericCaptions = info("res/sfx/songs/monster/monster.srt")
	if genericCaptions then captionsText = love.filesystem.read("res/sfx/songs/monster/monster.srt") end
	if englishCaptions then captionsText = love.filesystem.read("res/sfx/songs/monster/monster.en.srt") end
	if genericCaptions then captionsText = love.filesystem.read("res/sfx/songs/monster/monster." .. srtLUT[getNestedValue("config.system.language")] .. ".srt") end
	globalResources.obj.srtobj = modules.srt.new(captionsText)
end
Now parsed nodes work but the output is still nil, also i did a conscious decision of when there's no subtitle present at the time return an empty string witch ensures the same result as nil but avoiding to deal with nil on love.graphics.print() since for what i remember it doesn't like it
Attachments
Captura de pantalla de 2024-02-05 09-48-56.png
Captura de pantalla de 2024-02-05 09-48-56.png (132.28 KiB) Viewed 64798 times
Captura de pantalla de 2024-02-05 09-42-02.png
Captura de pantalla de 2024-02-05 09-42-02.png (131.33 KiB) Viewed 64798 times

Code: Select all

target = boardIndex.getWhosPeekingThisLine()
target:setObey(true)
RNavega
Party member
Posts: 385
Joined: Sun Aug 16, 2020 1:28 pm

Re: [LIBRARY] srt.lua A simple srt caption parser

Post by RNavega »

That's a cool IDE, it shows a stack / debug info, very useful. I code in Notepad++ like a peasant, it's just the text and that's it.
alejandroalzate wrote: Mon Feb 05, 2024 2:56 pm Now parsed nodes work but the output is still nil, also i did a conscious decision of when there's no subtitle present at the time return an empty string witch ensures the same result as nil but avoiding to deal with nil on love.graphics.print() since for what i remember it doesn't like it
That's a good debate, should it return nil or an empty string when the current time isn't sampling any subtitle nodes (i.e. the blank time between nodes) ?

There are good reasons for either case: return an empty string so you can plug :getText() directly into love.graphics.print() and not have to worry about it returning nil:

Code: Select all

-- If returning an empty string.
love.graphics.print(mySubtitle:getText(), ...)
Or, return nil in case you want to use it in boolean expressions, as only false and nil are falsy values in Lua. Everything else, including zero and empty strings, are truthy.

Code: Select all

-- If returning nil.
local text = mySubtitle:getText()
if text then
    love.graphics.print(text, ...)
end
PS there was a bug with nil indexes, I updated that code with it.
alejandroalzate
Citizen
Posts: 67
Joined: Sat May 08, 2021 9:45 pm

Re: [LIBRARY] srt.lua A simple srt caption parser

Post by alejandroalzate »

RNavega wrote: Tue Feb 06, 2024 4:28 am That's a cool IDE, it shows a stack / debug info, very useful. I code in Notepad++ like a peasant, it's just the text and that's it.
alejandroalzate wrote: Mon Feb 05, 2024 2:56 pm Now parsed nodes work but the output is still nil, also i did a conscious decision of when there's no subtitle present at the time return an empty string witch ensures the same result as nil but avoiding to deal with nil on love.graphics.print() since for what i remember it doesn't like it
That's a good debate, should it return nil or an empty string when the current time isn't sampling any subtitle nodes (i.e. the blank time between nodes) ?

There are good reasons for either case: return an empty string so you can plug :getText() directly into love.graphics.print() and not have to worry about it returning nil:

Code: Select all

-- If returning an empty string.
love.graphics.print(mySubtitle:getText(), ...)
Or, return nil in case you want to use it in boolean expressions, as only false and nil are falsy values in Lua. Everything else, including zero and empty strings, are truthy.

Code: Select all

-- If returning nil.
local text = mySubtitle:getText()
if text then
    love.graphics.print(text, ...)
end
PS there was a bug with nil indexes, I updated that code with it.
In the IDE: that ide is called ZeroBraneStudio (For me is 0 brain studio lol) my choice is sublime but when a bug escapes my comprehension i go to zbstudio
In the debate: my library spits an empty string when there's no sub available in the time this ensures that the font methods getWidth and getHeight doesn't brick itself, and "as only false and nil are falsy values in Lua. Everything else, including zero and empty strings, are truthy." for what i know 0 is treated as false as well, i might check but that is what i remember
I checked I've lived in a lie :cry: :

Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
> if 0 then
>> print("true")
>> else
>> print("false")
>> end
true


I know the clear oversight of an actual caption with and empty line but then that caption line is usseless anyway, so why bother for a real empty string.
my take when i do a check is

Code: Select all

local isTextPresent = mySub:getText() ~= ""
so i really want to keep the "empty string" behavior, since that bloated parse fucntion that you pointed out the first thing that will do is just clearing self.outputString to an empty string, if ANY condition fails the function avoids the heavy condition checks altogether

Code: Select all

target = boardIndex.getWhosPeekingThisLine()
target:setObey(true)
Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests