Posted 12 March 2015 - 02:56 PM
I am attempting to make a function return an unpacked table. Testing showed the table does have multiple values. As well separating the function from the rest of the program it returned values as expected…so something else in the program is making it not return correctly. I have spent some hours trying to fix this so figured maybe someone can give me some new ideas on whats wrong. Currently it is only returning the first value in the table "concat"
function which is failing:
I understand this is a ton of tightly packed messy code so I don't expect too many people to try and help as its difficult to even read but thanks to anyone who does try to figure this out in advance!
extra note: there may be a few bugs after the replace function as I am currently going through and revamping the code. This is the dev of the update and can't continue update/bug cracking without fixing this return issue. These bugs shouldn't be of any effect to the returning issue since the function only references to items defined before it.
EDIT:
to save effort I am assuming the cause is in lines 65-72 where im saving the function as a table using a __call metamethod. I don't know why this would cause it to not return multiple values though and I haven't managed to isolate the exact cause.
Spoiler
local snipeComment = {"--[[","{{FILESNIPE VAR HANDLE}}"," ","please do not edit anything in this comment block"," ","{ ,}","]]",}
local mv = {
__index = function(t,k)
local file = fs.open(k,"r")
if not file then return nil end
local total = {}
for line in file.readLine do
table.insert(total,line)
end
file.close()
return total
end;
__newindex = function(t,k,v)
if type(v)==nil then
fs.delete(k)
else
local file = fs.open(k,"w")
for i=1,#v do
file.writeLine(v[i])
end
file.close()
end
end;
}
local function init()
fileSnipeNew = nil
fileSnipeNew = setmetatable({
fileData = {},
fileName = "nil",
fileMode = false,
bypass = false,
fileIsVar = false,
handle = function(self,bool)
if not bool and not self.bypass and not self.fileIsVar and self.fileData[2]=="{{FILESNIPE VAR HANDLE}}" then
self.fileIsVar = {}
for i=1,7 do
table.insert(self.fileIsVar,self.fileData[1])
table.remove(self.fileData,1)
end
elseif not bypass and self.fileIsVar then
for i=#self.fileIsVar,1,-1 do
table.insert(self.fileData,1,self.fileIsVar[i])
end
self.fileIsVar = false
end
end,
},{
__index = function(t,k)
if t.fileMode then t.fileData=snipeAPIFiles[t.fileName] end
t:handle(true)
if t.fileData[2]~="{{FILESNIPE VAR HANDLE}}" then
for i=#snipeComment,1,-1 do
table.insert(t.fileData,1,snipeComment[i])
end
end
local var = textutils.unserialize(t.fileData[6]) or {}
return tostring(var[k]):sub(1,8)=="function" and loadstring("return "..var[k])() or var[k]
end;
__newindex = function(t,k,v)
if type(v)=="function" then
func = setmetatable({},{
__call = function(_,...)
return rawequal(t,({...})[1]) and v(...) or v(t,...)
end;
})
rawset(t,k,func)
else
if t.fileMode then t.fileData=snipeAPIFiles[t.fileName] end
t:handle(true)
if t.fileData[2]~="{{FILESNIPE VAR HANDLE}}" then
for i=#snipeComment,1,-1 do
table.insert(t.fileData,1,snipeComment[i])
end
snipeAPIFiles[t.fileName] = t.fileData
end
local var=textutils.unserialize(t.fileData[6]) or {}
var[k] = v
t.fileData[6] = textutils.serialize(var):gsub("\n","")
snipeAPIFiles[t.fileName] = t.fileData
end
end;
})
fileSnipeNew.getLine = function(self,...)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
local concat = {}
for _,line in ipairs(arg) do
line=line<0 and #self.fileData+(line+1) or line
table.insert(concat,line<#self.fileData and line>0 and self.fileData[line])
end
return unpack(concat)
end
fileSnipeNew.setLine = function(self,line,data)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
line=line<0 and #self.fileData+(line+1) or line
if line>#self.fileData then
for i=1,line-#self.fileData do
table.insert(self.fileData,"")
end
elseif line<1 then
repeat
table.insert(self.fileData,1,"")
line = line+1
until line>0
end
self.fileData[line] = data
self:handle(true)
snipeAPIFiles[self.fileName] = self.fileData
end
fileSnipeNew.len = function(self)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
return #self.fileData
end
fileSnipeNew.getFile = function(self)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
return self.fileData
end
fileSnipeNew.setFile = function(self,...)
self:handle(false)
self.fileData=type(arg[1])=="table" and arg[1] or arg
self:handle(true)
snipeAPIFiles[self.fileName] = self.fileData
end
fileSnipeNew.remLine = function(self,...)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
arg=type(arg[1])=="table" and arg[1] or arg
table.sort(arg,function(a,B)/>/>/>/>/> return a>b end)
for _,line in ipairs(arg) do
table.remove(self.fileData,line)
end
self:handle(true)
snipeAPIFiles[self.fileName]=self.fileData
end
fileSnipeNew.insert = function(self,line,data)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
if type(data)=="string" then table.insert(self.fileData,line,data)
elseif type(data)=="table" then
for i=#data,1,-1 do
table.insert(self.fileData,line,data[i])
end
end
self:handle(true)
snipeAPIFiles[self.fileName]=self.fileData
end
fileSnipeNew.find = function(self,str,whole)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
local instances = {}
for i=1,#self.fileData do
local t=1
local cut = {string.find(self.fileData[i],str,t)}
while cut[1] do
local s = self.fileData[i]:sub(cut[2]+1,cut[2]+1)
if not whole or s==" " or s=="?" or s=="," or s=="!" or s=="." or s=="\"" or s=="'" or s=="(" or s==")" or s=="=" or s=="" then
table.insert(instances,{i,cut[1]})
end
t=cut[2]+1
cut = {string.find(self.fileData[i],str,t)}
end
end
return instances
end
fileSnipeNew.swap = function(self,line1,line2)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
if line1<=#self.fileData and line2<=#self.fileData then
self.fileData[line1],self.fileData[line2]=self.fileData[line2],self.fileData[line1]
self:handle(true)
snipeAPIFiles[self.fileName]=self.fileData
end
end
fileSnipeNew.replace = function(self,old,new,index,whole)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
local tbl = self:find(old,whole)
local segment = self.fileData[tbl[index][1]]
segment = segment:sub(1,tbl[index][2]-1)..new..segment:sub(tbl[index][2]+old:len(),segment:len())
print(tostring(tbl[index][1]).." : "..tostring(segment))
self.fileData[tbl[index][1]] = segment
end
fileSnipeNew.replaceAll = function(self,old,new,whole)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
local tbl = self:find(old,whole)
for i=#tbl,1,-1 do
local segment = self:getLine(tbl[i][1])
segment = segment:sub(1,tbl[i][2]-1)..new..segment:sub(tbl[i][2]+old:len(),segment:len())
self:setLine(tbl[i][1],segment)
end
end
fileSnipeNew.append = function(self,...)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
arg=type(arg[1])=="table" and arg[1] or arg
for _,data in pairs(arg) do
table.insert(self.fileData,data)
end
self:handle(true)
snipeAPIFiles[self.fileName] = self.fileData
end
fileSnipeNew.combineLines = function(self,line1,line2,sep)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
sep = sep or " "
self.fileData[line1] = self.fileData[line1]..sep..self.fileData[line2]
table.remove(self.fileData,line2)
self:handle(true)
snipeAPIFiles[self.fileName] = self.fileData
end
fileSnipeNew.moveLine = function(self,from,to)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
from=(from<0 and #self.fileData+(from+1) or from) + (from>to and 1 or 0)
to=(to<0 and #self.fileData+(to+1) or to) + (to>from and 1 or 0)
table.insert(self.fileData,to+1,self.fileData[from])
table.remove(self.fileData,from)
self:handle(true)
snipeAPIFiles[self.fileName] = self.fileData
end
fileSnipeNew.concatLine = function(self,line,data)
if self.fileMode then self.fileData=snipeAPIFile[self.fileName] end
self:handle(false)
line=line<0 and #self.fileData+(line+1) or line
self.fileData[line] = self.fileData[line]..data
self:handle(true)
snipeAPIFiles[self.fileName] = self.fileData
end
fileSnipeNew.sepLines = function(self,line,sep)
if self.fileMode then self.fileData=snipeAPIFile[self.fileName] end
self:handle(false)
table.insert(self.fileData,line+1,self.fileData[line]:sub(sep,self.fileData[line]:len()))
self.fileData[line] = self.fileData[line]:sub(1,sep-1)
self:handle(true)
snipeAPIFiles[self.fileName] = self.fileData
end
fileSnipeNew.rawVar = function(self,key)
if self.fileMode then self.fileData=snipeAPIFile[self.fileName] end
local var = textutils.unserialize(self.fileData[6])
return type(var)~="nil" and var[key]
end
end
snipeAPIFiles = setmetatable({},mv)
function open(sFile,mode,bypass)
init()
fileSnipeNew.fileName = sFile
bypass,mode=type(mode)~="string" and mode or bypass,nil or bypass,type(mode)=="string" and mode or nil
fileSnipeNew.fileData = snipeAPIFiles[sFile] or {}
fileSnipeNew.fileMode=mode=="d"
fileSnipeNew.bypass = bypass
return fileSnipeNew
end
function which is failing:
fileSnipeNew.getLine = function(self,...)
if self.fileMode then self.fileData=snipeAPIFiles[self.fileName] end
self:handle(false)
local concat = {}
for _,line in ipairs(arg) do
line=line<0 and #self.fileData+(line+1) or line
table.insert(concat,line<#self.fileData and line>0 and self.fileData[line])
end
return unpack(concat)
end
I understand this is a ton of tightly packed messy code so I don't expect too many people to try and help as its difficult to even read but thanks to anyone who does try to figure this out in advance!
extra note: there may be a few bugs after the replace function as I am currently going through and revamping the code. This is the dev of the update and can't continue update/bug cracking without fixing this return issue. These bugs shouldn't be of any effect to the returning issue since the function only references to items defined before it.
EDIT:
to save effort I am assuming the cause is in lines 65-72 where im saving the function as a table using a __call metamethod. I don't know why this would cause it to not return multiple values though and I haven't managed to isolate the exact cause.
Edited on 12 March 2015 - 02:32 PM