Last Updated: February 25, 2016
·
728
· losinggeneration

Lua Discount

Continuing with my adventures in Markdown for mdcat and friends, one of my computers didn't have discount in the repos. Rather then just building the markdown command from the source, I thought it would be more fun to do a quick implementation of the command in Lua. (I also did it to have an excuse to post protip with a Lua tag.)

I decided to go with lua-discount instead of markdown (both installable through luarocks.) The reason is speed. To give a good rough estimate: to parse and display an 11M file it takes Lua markdown around 62 seconds, discount markdown about 0.87 seconds, and lua-discount about 0.9 seconds with Lua 5.1.5. I find this to be very acceptable speed wise and it the results aren't surprising since they're using basically the same code (one is just being call from within Lua.)

Now, onto how I implemented my lua-discount markdown command. It's actually very straight forward and how you'd likely expect it to be implemented. I check for command line arguments and send each file to discount and write out the results. If there was no command line arguments, I read from stdin instead.

discount=require("discount")
if #arg > 0 then
    for _,v in ipairs(arg) do
        local lines = ""
        local f = io.open(v, "r")
        if not f then
            io.output(io.stderr):write(string.format([[%s: No such file or directory\n]], v))
            os.exit(1)
        end

        io.write(discount(f:read("*a")))
        f:close()
    end
else
    local lines = ''
    while true do
        local line = io.read()
        if not line then
            break
        end
        lines = string.format('%s\\\n%s', lines, line)
    end
    io.write(discount(lines))
end

In the tradition of mdcat and friends, I decided to embed the above Lua code into a shell function. So here's the shell function (minus the above code marked with <LUA MARKDOWN CODE>

function markdown()
{
    lua5.1 <(echo "$(cat << EOLUA
    <LUA MARKDOWN CODE>
EOLUA
    )") $*
}

In all, the shell function is 30 lines with the Lua code embedded.

Now, the only gotcha with the Lua implementation is that it doesn't handle very large files. To clarify "very large" I'll say this: a 41M file worked fine, but a 56M file fails with this implementation. The 56M file however works with Discount's markdown. I haven't really looked into exactly why, but I think I'm ok with not being able to use this implementation for files larger than 41M-56M.