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

Help with basic OS browser

Started by KaoS, 29 August 2012 - 11:50 AM
KaoS #1
Posted 29 August 2012 - 01:50 PM
Hey everyone, I have just started working on a basic OS system which I want to develop but I have hit a roadblock, the function that builds a list of all files and directories gives an error when I try to enter a second directory, here is the code (a little messy as I just started earlier today while busy on other things, apologies)

The program code:
Spoiler
local function count(input)
if type(input)~="table" then
print("incorrect input: "..tostring(input))
return
end
local int=0
for a in pairs(input) do
int=int+1
end
return int
end

local function combinet(one,two)
if type(one)~="table" or type(two)~="table" then
print("incorrect input")
return
end
for k,v in pairs(two) do
if type(k)=="number" then
one[count(one)+1]=v
else
one[k]=v
end
end
return one
end

function check(input)
if not fs.isDir(shell.resolve(input)) then
return menu.alternate({{'edit', 'run'}},{{{shell.run,"edit",input},{shell.run,input}}})
end
end

while true do
local currentdirs={{}}
local currentfiles={{}}
local cds={{}}
local acts={{}}
for k,v in pairs(fs.list(shell.dir())) do
if fs.isDir(shell.resolve(v)) then
if count(currentdirs[count(currentdirs)])==3 then
currentdirs[count(currentdirs)+1]={}
cds[count(currentdirs)+1]={}
end
currentdirs[count(currentdirs)][count(currentdirs[count(currentdirs)])+1]=v
cds[count(currentdirs)][count(currentdirs[count(currentdirs)])]={shell.setDir,shell.resolve(v)}
else
if count(currentfiles[count(currentfiles)])==3 then
currentfiles[count(currentfiles)+1]={}
acts[count(currentfiles)+1]={}
end
currentfiles[count(currentfiles)][count(currentfiles[count(currentfiles)])+1]=v
acts[count(currentfiles)][count(currentfiles[count(currentfiles)])]={check,v}
end
end
for k,v in pairs(currentfiles) do
currentdirs[count(currentdirs)+1]=v
end
for k,v in pairs(acts) do
cds[count(cds)+1]=v
end

for k,v in pairs(currentdirs) do
for a,b in pairs(v) do
print(k.." "..a.." "..B)/>/>
end
end
menu.alternate(currentdirs,cds)
end

the menu api that I developed and use in it:
Spoiler
function generate(choices, results, spacing)
spacing=tonumber(spacing) or 7
if type(choices)~="table" or type(results)~="table" then
print("ERROR GENERATING MENUnINPUT INCORRECT")
return nil
end
local selectedx=1
local selectedy=1
while true do
term.clear()
for y=1,#choices do
for x=1,#choices[y] do
if x==selectedx and y==selectedy then
term.setCursorPos(x*spacing-spacing+1,y)
write(">"..choices[y][x].."<")
else
term.setCursorPos(x*spacing-spacing+2,y)
write(choices[y][x])
end
end
end
print("")


while true do
local event,param1=os.pullEvent("key")
if param1==203 and selectedx>1 then
selectedx=selectedx-1
break
end
if param1==205 and selectedx<#choices[selectedy] then
selectedx=selectedx+1
break
end
if param1==200 and selectedy>1 then
selectedy=selectedy-1
break
end
if param1==208 and selectedy<#choices then
selectedy=selectedy+1
break
end
if param1==28 then
return loadstring(results[selectedy][selectedx])()
end
end
if selectedx>#choices[selectedy] then
selectedx=#choices[selectedy]
end
end
end

function alternate(choices, results, spacing)
spacing=tonumber(spacing) or 7
if type(choices)~="table" or type(results)~="table" then
print("ERROR GENERATING MENUnINPUT INCORRECT")
return nil
end
local selectedx=1
local selectedy=1
while true do
term.clear()
for y=1,#choices do
for x=1,#choices[y] do
if x==selectedx and y==selectedy then
term.setCursorPos(x*spacing-spacing+1,y)
write(">"..choices[y][x].."<")
else
term.setCursorPos(x*spacing-spacing+2,y)
write(choices[y][x])
end
end
end
print("")


while true do
local event,param1=os.pullEvent("key")
if param1==203 and selectedx>1 then
selectedx=selectedx-1
break
end
if param1==205 and selectedx<#choices[selectedy] then
selectedx=selectedx+1
break
end
if param1==200 and selectedy>1 then
selectedy=selectedy-1
break
end
if param1==208 and selectedy<#choices then
selectedy=selectedy+1
break
end
if param1==28 then
if results[selectedy][selectedx][3] then
return results[selectedy][selectedx][1](results[selectedy][selectedx][2],results[selectedy][selectedx][3])
else
return results[selectedy][selectedx][1](results[selectedy][selectedx][2])
end
end
end
if selectedx>#choices[selectedy] then
selectedx=#choices[selectedy]
end
end
end

It returns
53: index expected, got nil

any help would be greatly appreciated (just please don't tell me to steal redworks code. this is about building it myself so I can add handles for additional uses and functionality)

EDIT: I successfully open files and folders but when I try to open rom/anydirectory it crashes :)/>/>
Kolpa #2
Posted 29 August 2012 - 03:40 PM
Hey everyone, I have just started working on a basic OS system which I want to develop but I have hit a roadblock, the function that builds a list of all files and directories gives an error when I try to enter a second directory, here is the code (a little messy as I just started earlier today while busy on other things, apologies)

The program code:
Spoiler
local function count(input)
if type(input)~="table" then
print("incorrect input: "..tostring(input))
return
end
local int=0
for a in pairs(input) do
int=int+1
end
return int
end

local function combinet(one,two)
if type(one)~="table" or type(two)~="table" then
print("incorrect input")
return
end
for k,v in pairs(two) do
if type(k)=="number" then
one[count(one)+1]=v
else
one[k]=v
end
end
return one
end

function check(input)
if not fs.isDir(shell.resolve(input)) then
return menu.alternate({{'edit', 'run'}},{{{shell.run,"edit",input},{shell.run,input}}})
end
end

while true do
local currentdirs={{}}
local currentfiles={{}}
local cds={{}}
local acts={{}}
for k,v in pairs(fs.list(shell.dir())) do
if fs.isDir(shell.resolve(v)) then
if count(currentdirs[count(currentdirs)])==3 then
currentdirs[count(currentdirs)+1]={}
cds[count(currentdirs)+1]={}
end
currentdirs[count(currentdirs)][count(currentdirs[count(currentdirs)])+1]=v
cds[count(currentdirs)][count(currentdirs[count(currentdirs)])]={shell.setDir,shell.resolve(v)}
else
if count(currentfiles[count(currentfiles)])==3 then
currentfiles[count(currentfiles)+1]={}
acts[count(currentfiles)+1]={}
end
currentfiles[count(currentfiles)][count(currentfiles[count(currentfiles)])+1]=v
acts[count(currentfiles)][count(currentfiles[count(currentfiles)])]={check,v}
end
end
for k,v in pairs(currentfiles) do
currentdirs[count(currentdirs)+1]=v
end
for k,v in pairs(acts) do
cds[count(cds)+1]=v
end

for k,v in pairs(currentdirs) do
for a,b in pairs(v) do
print(k.." "..a.." "..B)/>/>
end
end
menu.alternate(currentdirs,cds)
end

the menu api that I developed and use in it:
Spoiler
function generate(choices, results, spacing)
spacing=tonumber(spacing) or 7
if type(choices)~="table" or type(results)~="table" then
print("ERROR GENERATING MENUnINPUT INCORRECT")
return nil
end
local selectedx=1
local selectedy=1
while true do
term.clear()
for y=1,#choices do
for x=1,#choices[y] do
if x==selectedx and y==selectedy then
term.setCursorPos(x*spacing-spacing+1,y)
write(">"..choices[y][x].."<")
else
term.setCursorPos(x*spacing-spacing+2,y)
write(choices[y][x])
end
end
end
print("")


while true do
local event,param1=os.pullEvent("key")
if param1==203 and selectedx>1 then
selectedx=selectedx-1
break
end
if param1==205 and selectedx<#choices[selectedy] then
selectedx=selectedx+1
break
end
if param1==200 and selectedy>1 then
selectedy=selectedy-1
break
end
if param1==208 and selectedy<#choices then
selectedy=selectedy+1
break
end
if param1==28 then
return loadstring(results[selectedy][selectedx])()
end
end
if selectedx>#choices[selectedy] then
selectedx=#choices[selectedy]
end
end
end

function alternate(choices, results, spacing)
spacing=tonumber(spacing) or 7
if type(choices)~="table" or type(results)~="table" then
print("ERROR GENERATING MENUnINPUT INCORRECT")
return nil
end
local selectedx=1
local selectedy=1
while true do
term.clear()
for y=1,#choices do
for x=1,#choices[y] do
if x==selectedx and y==selectedy then
term.setCursorPos(x*spacing-spacing+1,y)
write(">"..choices[y][x].."<")
else
term.setCursorPos(x*spacing-spacing+2,y)
write(choices[y][x])
end
end
end
print("")


while true do
local event,param1=os.pullEvent("key")
if param1==203 and selectedx>1 then
selectedx=selectedx-1
break
end
if param1==205 and selectedx<#choices[selectedy] then
selectedx=selectedx+1
break
end
if param1==200 and selectedy>1 then
selectedy=selectedy-1
break
end
if param1==208 and selectedy<#choices then
selectedy=selectedy+1
break
end
if param1==28 then
if results[selectedy][selectedx][3] then
return results[selectedy][selectedx][1](results[selectedy][selectedx][2],results[selectedy][selectedx][3])
else
return results[selectedy][selectedx][1](results[selectedy][selectedx][2])
end
end
end
if selectedx>#choices[selectedy] then
selectedx=#choices[selectedy]
end
end
end

It returns
53: index expected, got nil

any help would be greatly appreciated (just please don't tell me to steal redworks code. this is about building it myself so I can add handles for additional uses and functionality)

EDIT: I successfully open files and folders but when I try to open rom/anydirectory it crashes :)/>/>
the rom folders are write protected check if you are just looking for content and not trying to edit something, also take a look at the ls or dir programm
KaoS #3
Posted 29 August 2012 - 03:43 PM
that is what I modelled it after, it just uses the fs.list command and shell.dir command, nothing trying to write to anything
Kolpa #4
Posted 29 August 2012 - 04:11 PM
hmm that's odd
KaoS #5
Posted 30 August 2012 - 07:29 AM
yeah tell me about it, I am at a loss because you can browse through any number of directories but not into a rom subfolder
BigSHinyToys #6
Posted 30 August 2012 - 07:41 AM
I don't know if this will be of help but here is a File Browser I made and it works with folder in ROM.
http://pastebin.com/9itmSeyA

It can only launch programs and is not complete.
KaoS #7
Posted 30 August 2012 - 07:48 AM
wait a sec, I just realised this is probably not CC, I am using the emulator from these forums, maybe that is why it does not work

EDIT: and @BigSHinyToys: wow, nice code. I find it hard to manage such a large code and keep it organised, I would also recommend making barrier a function that recalculates the width and height of the screen each time etc so they can change screen size and it would still work, there are a few things I would change but I guess it's mainly just preference, great code dude
BigSHinyToys #8
Posted 30 August 2012 - 08:27 AM
line 53 causes that error because there in no table in the main table at that position.

I have added a fix but other errors are still there. see if you can track them down
http://pastebin.com/dsCJrU2E
KaoS #9
Posted 30 August 2012 - 08:34 AM
what do you mean? if that is the problem then the if statement should catch it
KaoS #10
Posted 30 August 2012 - 08:57 AM
I finally found the error on line 50, it now works fine


local function count(input)
if type(input)~="table" then
  print("incorrect input: "..tostring(input))
  return
end
local int=0
for a in pairs(input) do
  int=int+1
end
return int
end
local function combinet(one,two)
if type(one)~="table" or type(two)~="table" then
  print("incorrect input")
  return
end
for k,v in pairs(two) do
  if type(k)=="number" then
   one[count(one)+1]=v
  else
   one[k]=v
  end
end
return one
end
function check(input)
if not fs.isDir(shell.resolve(input)) then
  return menu.alternate({{'edit', 'run'}},{{{shell.run,"edit",input},{shell.run,input}}})
end
end
while true do
local currentdirs={{}}
local currentfiles={{}}
local cds={{}}
local acts={{}}
for k,v in pairs(fs.list(shell.dir())) do
  if fs.isDir(shell.resolve(v)) then
   if count(currentdirs[count(currentdirs)])==3 then
	currentdirs[count(currentdirs)+1]={}
	cds[count(currentdirs)+1]={}
   end
   currentdirs[count(currentdirs)][count(currentdirs[count(currentdirs)])+1]=v
   cds[count(currentdirs)][count(currentdirs[count(currentdirs)])]={shell.setDir,shell.resolve(v)}
  else
   if count(currentfiles[count(currentfiles)])==3 then
	currentfiles[count(currentfiles)+1]={}
	acts[count(currentfiles)]={}
   end
   currentfiles[count(currentfiles)][count(currentfiles[count(currentfiles)])+1]=v
   acts[count(currentfiles)][count(currentfiles[count(currentfiles)])]={check,v}
  end
end
for k,v in pairs(currentfiles) do
  currentdirs[count(currentdirs)+1]=v
end
for k,v in pairs(acts) do
  cds[count(cds)+1]=v
end
menu.alternate(currentdirs,cds)
end

now I just need to add functionality for if there are no directories or files
KaoS #11
Posted 30 August 2012 - 09:54 AM
And here is the final result:

Spoiler


local function count(input)
if type(input)~="table" then
print("incorrect input: "..tostring(input))
return
end
local int=0
for a in pairs(input) do
int=int+1
end
return int
end

local function getlongest(input)
if type(input)~="table" then
print("incorrect input")
return
end
local int=0
for k,v in pairs(input) do
for a,b in pairs(v) do
if string.len(:)/>/>>int then
int=#b
end
end
end
return int
end

function check(input)
if not fs.isDir(shell.resolve(input)) then
return menu.alternate({{'edit', 'run', 'run with parameters'},{'delete'}},{{{shell.run,"edit",input},{shell.run,input},{runwith,input}},{{fs.delete,input}}})
end
end

function runwith(input,params)
local params=params or {}
while menu.alternate({{'done','add param'}},{{{shell.run,input,unpack(params)},{addparam,params}}})=='added' do
end
end

function addparam(params)
print('Current parameters: ')
for k,v in pairs(params) do
print(v)
end
write('enter new parameter: ')
params[(#params or 0)+1]=read()
return 'added'
end

function createnew()
term.clear()
term.setCursorPos(1,1)
write('enter new file name: ')
local new=read()
if new=='' then
print('Invalid entry')
sleep(2)
elseif fs.exists(new) then
print('File already exists')
sleep(2)
else
shell.run('edit',new)
end
end

while true do
if shell.dir()=="" then
currentdirs={{}}
cds={{}}
else
currentdirs={{".."}}
cds={{{shell.setDir,shell.resolve("..")}}}
end

local currentfiles={{"new"}}
local acts={{{createnew}}}
for k,v in pairs(fs.list(shell.dir())) do
if fs.isDir(shell.resolve(v)) then
if count(currentdirs[count(currentdirs)])==3 then
currentdirs[count(currentdirs)+1]={}
cds[count(currentdirs)]={}
end
currentdirs[count(currentdirs)][count(currentdirs[count(currentdirs)])+1]=v
cds[count(currentdirs)][count(currentdirs[count(currentdirs)])]={shell.setDir,shell.resolve(v)}
else
if count(currentfiles[count(currentfiles)])==3 then
currentfiles[count(currentfiles)+1]={}
acts[count(currentfiles)]={}
end
currentfiles[count(currentfiles)][count(currentfiles[count(currentfiles)])+1]=v
acts[count(currentfiles)][count(currentfiles[count(currentfiles)])]={check,v}
end
end
for k,v in pairs(currentfiles) do
currentdirs[count(currentdirs)+1]=v
end
for k,v in pairs(acts) do
cds[count(cds)+1]=v
end

menu.alternate(currentdirs,cds,getlongest(currentdirs)+2)
end

with menu function
Spoiler

function generate(choices, results, spacing)
spacing=tonumber(spacing) or 7
if type(choices)~="table" or type(results)~="table" then
  print("ERROR GENERATING MENUnINPUT INCORRECT")
  return nil
end
local selectedx=1
local selectedy=1
while true do
  term.clear()
  for y=1,#choices do
   for x=1,#choices[y] do
    if x==selectedx and y==selectedy then
	 term.setCursorPos(x*spacing-spacing+1,y)
	 write(">"..choices[y][x].."<")
    else
	 term.setCursorPos(x*spacing-spacing+2,y)
	 write(choices[y][x])
    end
   end
  end
  print("")

  while true do
   local event,param1=os.pullEvent("key")
   if param1==203 and selectedx>1 then
    selectedx=selectedx-1
    break
   end
   if param1==205 and selectedx<#choices[selectedy] then
    selectedx=selectedx+1
    break
   end
   if param1==200 and selectedy>1 then
    selectedy=selectedy-1
   break
   end
   if param1==208 and selectedy<#choices then
    selectedy=selectedy+1
    break
   end
   if param1==28 then
    return loadstring(results[selectedy][selectedx])()
   end
  end
  if selectedx>#choices[selectedy] then
   selectedx=#choices[selectedy]
  end
end
end
function alternate(choices, results, spacing)
spacing=tonumber(spacing) or 7
if type(choices)~="table" or type(results)~="table" then
  print("ERROR GENERATING MENUnINPUT INCORRECT")
  return nil
end
local selectedx=1
local selectedy=1
while true do
  term.clear()
  for y=1,#choices do
   for x=1,#choices[y] do
    if x==selectedx and y==selectedy then
	 term.setCursorPos(x*spacing-spacing+1,y)
	 write(">"..choices[y][x].."<")
    else
	 term.setCursorPos(x*spacing-spacing+2,y)
	 write(choices[y][x])
    end
   end
  end
  print("")

  while true do
   local event,param1=os.pullEvent("key")
   if param1==203 and selectedx>1 then
    selectedx=selectedx-1
    break
   end
   if param1==205 and selectedx<#choices[selectedy] then
    selectedx=selectedx+1
    break
   end
   if param1==200 and selectedy>1 then
    selectedy=selectedy-1
   break
   end
   if param1==208 and selectedy<#choices then
    selectedy=selectedy+1
    break
   end
   if param1==28 then
    local params={}
    for k,v in pairs(results[selectedy][selectedx]) do
	 if k~=1 then
	  params[#params+1]=v
	 end
    end
    return results[selectedy][selectedx][1](unpack(params))
   end
  end
  if selectedx>#choices[selectedy] then
   selectedx=#choices[selectedy]
  end
end
end

EDIT: updated
Edited on 30 August 2012 - 10:54 AM