This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
vodamark's profile picture

Custom API best practices

Started by vodamark, 07 August 2016 - 07:55 PM
vodamark #1
Posted 07 August 2016 - 09:55 PM
I'd like to write my own API and use it in other scripts.

This is an example of an API I want to use (all code is still work in progress):

Log = {}
Log.__index = Log
function Log.create(fileName)
  local _ = {}
  setmetatable(_, Log)
  _.fileName = fileName
  return _
end
function Log:add(message)
  local _ = io.open(self:fileName, "a")
  io.output(_)
  io.write(message)
  io.flush()
end
function Log:addLine(message)
  self:add(message + "\r\n")
end
function Log:clear()
  local _ = io.open(self:fileName, "w+")
  io.output(_)
  io.write("")
  io.flush()
end

Ideally I'd like it used something like this:

os.loadAPI("Log")
log = Log.create("main.log")
log:addLine("Hello!")

This is how you'd do it in a "normal" lua environment with "require" (which has been removed from ComputerCraft), as far as I've read. But this is not working. It says "File not found". If I change the first line like this:

os.loadAPI("Log.lua")
Then I get this error:

bios:14: [string "Log.lua"]:12: function arguments expected

One thing I'd really like to keep is the ".lua" extension on my file, because I'm using an external editor to write this code and the extension ensures my editor recognizing the file as lua code.

So, the question is… How to write things like this? Is there a recommended way to do it?
Lyqyd #2
Posted 07 August 2016 - 10:08 PM
Check out the vector API that comes with ComputerCraft. It's an example of how you'd do something like this.
Bomb Bloke #3
Posted 08 August 2016 - 04:24 AM
A quick note on os.loadAPI() - it assigns your API script a custom environment table, executes its code, copies everything from the environment table into a new one named after the API file, and dumps that final result into _G.

This raises two important points - one, making your own "Log" table is redundant (as you'll see in the other API files included with ComputerCraft, eg the aforementioned vector API), and two, it means that sticking a period into your API filenames complicates matters.

For example, if you do os.loadAPI("Log.lua"), then the loaded API will end up as _G["Log.lua"]… which can't be referred to as _G.Log.lua.

You can work around this, of course, by simply shuffling the key around after loading:

os.loadAPI("Log.lua")

_G.Log = _G["Log.lua"]

_G["Log.lua"] = nil

Other users have also posted their own code in the APIs and Utilities section for dealing with such scenarios. I think there might even be a makeshift version of "require" in there somewhere.