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

returns of os.loadAPI()

Started by ReBraLaCC, 29 September 2016 - 02:46 PM
ReBraLaCC #1
Posted 29 September 2016 - 04:46 PM
So I was curious if you could get other returns other than true from os.loadAPI()

here was the code i had:

local gamePath = "Jetpack/"
local apiPath = gamePath.."api/"
apis = {"log"}
os.loadAPI(apiPath.."log")
local add = log.add

log.set(gamePath.."logs","log-"..os.day(),".gl")
function loadAPIs()
str = ""
add("Loading APIs...")
for k,v in pairs(fs.list(apiPath)) do
  if v ~= "log" then
   os.loadAPI(apiPath..v)
   table.insert(apis,v)
  end
  total = k
end
for k,v in pairs(apis) do
  str = v..","..str
end
add("Loaded:",str)
add("Total APIs: #"..total)
end
loadAPIs()

maybe i could just make a function in each API to get the version but i was wondering if there was a way :)/>

– ReBraLa

** Indention was better, website edited it like this

*** Have a return in the API as

local version = 1.3213123
return version
TheRockettek #2
Posted 29 September 2016 - 04:47 PM
There's false :D/> Also I believe it can return on a second variable what went wrong (The api doesn't work, it's already loaded .etc)
KingofGamesYami #3
Posted 29 September 2016 - 04:54 PM
No. os.loadAPI will always return true or false. You could write your own os.loadAPI (or just modify the existing one) to make it return values.
ReBraLaCC #4
Posted 29 September 2016 - 05:01 PM
No. os.loadAPI will always return true or false. You could write your own os.loadAPI (or just modify the existing one) to make it return values.

Okay, I'll think about something! question know any reason why it won't add the str from

for k,v in pairs(apis) do
  str = v..","..str
end
add("Loaded:",str)
add("Total APIs: #"..total)
to the log?
ReBraLaCC #5
Posted 29 September 2016 - 05:14 PM
– Snip

Solved the getting version with this

local file = fs.open(gamePath.."api-versions","r")
local versions = textutils.unserialise(file.readAll())
file.close()
function getVersion(api)
if versions[api] then
  return versions[api]
else
  return 0
end
end
Sewbacca #6
Posted 29 September 2016 - 08:53 PM
I wouldn't use numbers for the versions, because they don't support (and they shouldn't) multiple '.'.
I would solve it so:

local function collect (sContent) -- use File.readAll() as a argument
  sContent = sContent .. '\n'
  local tRes = {}
  for sName, sVersion in sContent:gmatch '([%a_][%a%w_]*)=([%d%.]*)\n' do
	tRes[sName] = sVersion
  end
  return tRes
end
Now you can add your data

API1=0.0.0.1
API2=!asdasd -- will be ignored (wbi)
Code 123 -- wbi
text 1234 -- wbi
ZAPI=546.00 -- won't be ignored
-- wbi
-- wbi
You can write into files with this function:

function saveCollected (tCollected, handle) -- you have to give a handle, opened with fs.open(sDest, 'w') or fs.open(sDest, 'a')
  for sName, sVersion in pairs(tCollected) do
	if sName:match '[%a_][%a%w_]*' and sVersion:match '[%d%.]*' then
		handle.writeLine(sName .. '=' .. sVersion)
	end
  end
  handle.flush() -- if you want to close the file, use saveCollected(...).close() or edit this line to handle.close()
  return handle
end

And yes, i am bored.
Edited on 29 September 2016 - 06:54 PM
thecrimulo #7
Posted 30 September 2016 - 11:08 PM
You can use the original os.loadAPI code, and then make it return the environment:

function os.loadAPI( _sPath )
    local sName = fs.getName( _sPath )
    if tAPIsLoading[sName] == true then
        printError( "API "..sName.." is already being loaded" )
        return false
    end
    tAPIsLoading[sName] = true

    local tEnv = {}
    setmetatable( tEnv, { __index = _G } )
    local fnAPI, err = loadfile( _sPath, tEnv )
    if fnAPI then
        local ok, err = pcall( fnAPI )
        if not ok then
            printError( err )
            tAPIsLoading[sName] = nil
            return false
        end
    else
        printError( err )
        tAPIsLoading[sName] = nil
        return false
    end
    
    local tAPI = {}
    for k,v in pairs( tEnv ) do
        if k ~= "_ENV" then
            tAPI[k] =  v
        end
    end

    _G[sName] = tAPI    
    tAPIsLoading[sName] = nil
    return true, tAPI -- Added tAPI here
end

Sewbacca #8
Posted 30 September 2016 - 11:13 PM
You can use the original os.loadAPI code, and then make it return the environment:

function os.loadAPI( _sPath )
	local sName = fs.getName( _sPath )
	if tAPIsLoading[sName] == true then
		printError( "API "..sName.." is already being loaded" )
		return false
	end
	tAPIsLoading[sName] = true

	local tEnv = {}
	setmetatable( tEnv, { __index = _G } )
	local fnAPI, err = loadfile( _sPath, tEnv )
	if fnAPI then
		local ok, err = pcall( fnAPI )
		if not ok then
			printError( err )
			tAPIsLoading[sName] = nil
			return false
		end
	else
		printError( err )
		tAPIsLoading[sName] = nil
		return false
	end
	
	local tAPI = {}
	for k,v in pairs( tEnv ) do
		if k ~= "_ENV" then
			tAPI[k] =  v
		end
	end

	_G[sName] = tAPI	
	tAPIsLoading[sName] = nil
	return true, tAPI -- Added tAPI here
end

It won't work i think, because tAPIsLoading isn't declared. Also, i propose, to don't load it into _G, because the user can load config data, without loading the config into _G. Also i would give a normal table, to prevent loading a virus through the config data.
thecrimulo #9
Posted 01 October 2016 - 12:33 AM
You can use the original os.loadAPI code, and then make it return the environment:

function os.loadAPI( _sPath )
	local sName = fs.getName( _sPath )
	if tAPIsLoading[sName] == true then
		printError( "API "..sName.." is already being loaded" )
		return false
	end
	tAPIsLoading[sName] = true

	local tEnv = {}
	setmetatable( tEnv, { __index = _G } )
	local fnAPI, err = loadfile( _sPath, tEnv )
	if fnAPI then
		local ok, err = pcall( fnAPI )
		if not ok then
			printError( err )
			tAPIsLoading[sName] = nil
			return false
		end
	else
		printError( err )
		tAPIsLoading[sName] = nil
		return false
	end
	
	local tAPI = {}
	for k,v in pairs( tEnv ) do
		if k ~= "_ENV" then
			tAPI[k] =  v
		end
	end

	_G[sName] = tAPI	
	tAPIsLoading[sName] = nil
	return true, tAPI -- Added tAPI here
end

It won't work i think, because tAPIsLoading isn't declared. Also, i propose, to don't load it into _G, because the user can load config data, without loading the config into _G. Also i would give a normal table, to prevent loading a virus through the config data.
I may have skipped one or two lines so it isn't declared on the function itself. And, its loadAPI that loads it into _G, you can perfectly not, also you can give it a custom environment
houseofkraft #10
Posted 02 October 2016 - 02:05 AM
If you wanted you can do this


local oldLoadAPI = os.loadAPI

os.loadAPI = function(api)
    oldLoadAPI(api)
    return version
end
Bomb Bloke #11
Posted 02 October 2016 - 02:45 AM
… and "version" is set where…?
houseofkraft #12
Posted 02 October 2016 - 03:31 AM
He said:
local version = 1.3213123
Bomb Bloke #13
Posted 02 October 2016 - 05:32 AM
Yeaaah…

Little problem with that - executing such a line in the API isn't going to make such a variable available to your override function. He was hoping he could have the API return such a value on-load, but os.loadAPI() would need to be rather more thoroughly overridden than that in order to receive it.

Personally I'd just define a getVersion() within the API file.