if not _G["wojbieGlobalsTable"] then
_G["wojbieGlobalsTable"]={}
end

local tArg={...}

if not wojbieGlobalsTable.vfiles and not wojbieGlobalsTable.vfunc then
wojbieGlobalsTable.vfiles={}
wojbieGlobalsTable.vfunc={}

local function save(A,B) local file = fs.open(tostring(A),"w") file.write(B) file.close() end
local function saveT(A,B) save(A,textutils.serialize(B)) end
local function saveTH(A,B) save(A,string.gsub(textutils.serialize(B),"},","},\r\n")) end
local function get(A) local file = fs.open(tostring(A),"r") if not file then return false end local data = file.readAll() file.close() if data then return data end end
local function getT(A) local data = get(A) if data then data = textutils.unserialize(data) end if data then return data end end


--save dir is next to shell unless someone instaled it as main shell. Then save all data in root
local dir= (shell and shell.getRunningProgram and shell.getRunningProgram()) or "/" 
dir=string.sub(dir,1,#dir-#fs.getName(dir))

wojbieGlobalsTable.vfunc.dir=dir  --this is for shell to use in future -- Also for other program i am using.

-- programs to load into virtual filesystem

local list="local tArgs = { ... }\
local sDir = shell.dir()\
local i=1\
local all=false\
if tArgs[i] == \"-a\" then\
	all=true\
	i=i+1\
end\
if tArgs[i] ~= nil then\
	sDir = shell.resolve( tArgs[i] )\
	i=i+1\
end\
if tArgs[i] == \"-a\" then\
	all=true\
	i=i+1\
end\
local tAll = fs.list( sDir )\
local tFiles = {}\
local tVFiles = {}\
local tDirs = {}\
local tVDirs = {}\
for n, sItem in pairs( tAll ) do\
	if all or string.sub( sItem, 1, 1 ) ~= \".\" then\
		local sPath = fs.combine( sDir, sItem )\
		if wojbieGlobalsTable and wojbieGlobalsTable.vfunc and wojbieGlobalsTable.vfunc.isVirt(sPath) then\
			if fs.isDir( sPath ) then\
				table.insert( tVDirs, sItem )\
			else\
				table.insert( tVFiles, sItem )\
			end\
		else\
			if fs.isDir( sPath ) then\
				table.insert( tDirs, sItem )\
			else\
				table.insert( tFiles, sItem )\
			end\
		end\
	end\
end\
table.sort( tDirs ) table.sort( tVDirs ) table.sort( tFiles ) table.sort( tVFiles )\
if term.isColour() then\
	textutils.pagedTabulate( colors.green , tDirs ,colors.lime, tVDirs, colors.white, tFiles, colors.lightGray , tVFiles )\
else\
	textutils.pagedTabulate( tDirs , tVDirs , tFiles , tVFiles)\
end"
local pastebinLogin="--[[ File Useage --]]\
local function save(A,B) local file = fs.open(tostring(A),\"w\") file.write(B) file.close() end\
local function saveT(A,B) save(A,textutils.serialize(B)) end\
local function saveTH(A,B) save(A,string.gsub(textutils.serialize(B),\"},\",\"},\\r\\n\")) end\
local function get(A) local file = fs.open(tostring(A),\"r\") if not file then return false end local data = file.readAll() file.close() if data then return data end end\
local function getT(A) local data = get(A) if data then data = textutils.unserialize(data) end if data then return data end end\
\
--[[ Settings --]]\
\
local api_dev_key=\"6ee24782806f592dc9b3be30960fe117\"\
local api_user_key=\"\"\
local virtual=false\
local dir=shell.getRunningProgram()\
dir=string.sub(dir,1,#dir-#fs.getName(dir))\
\
--[[ Tests --]]\
\
if not http then\
print(\"I need http Api to be on to work. Sorry.\")\
end\
\
if fs.isReadOnly(shell.getRunningProgram()) then\
	if wojbieGlobalsTable and wojbieGlobalsTable.vfiles and wojbieGlobalsTable.vfunc then\
		virtual=true\
	else\
		print(\"File is in read-only area - can't procced\") return\
	end\
end\
\
--[[ Saving code --]]\
local function saving(A,B)\
	if virtual then\
		wojbieGlobalsTable.vfunc.virtualize(A,B)\
	else\
		if B then save(A,B) else fs.makeDir(A) end\
	end\
end\
\
--[[ Decoding list --]]\
local function tabulate(A)\
    local out = {}\
    for i, k in string.gmatch(A, \"<(.-)>(.-)</%1>\") do\
        local temp = {}\
        for j, l in string.gmatch(k, \"<\"..i..\"_(.-)>(.-)</\"..i..\"_%1>\") do\
            temp[j] = l\
        end\
        table.insert(out,temp)\
    end\
    return out\
end\
\
--[[ Login api code --]]\
local function login(api_user_name,api_user_password)\
if type(api_user_name)~=\"string\" or type(api_user_password)~=\"string\" then error(\"Expected string, string\",2) end\
handle=http.post(\"http://pastebin.com/api/api_login.php\",\"api_user_name=\"..textutils.urlEncode(api_user_name)..\"&api_user_password=\"..textutils.urlEncode(api_user_password)..\"&api_dev_key=\"..textutils.urlEncode(api_dev_key))\
local out=handle.readAll()\
handle.close()\
return out\
end\
\
--[[ List api code --]]\
local function listall(api_user_key,api_results_limit)\
if type(api_user_key)~=\"string\" or type(api_results_limit)~=\"string\" then error(\"Expected string, string\",2) end\
handle=http.post(\"http://pastebin.com/api/api_post.php\",\"api_user_key=\"..textutils.urlEncode(api_user_key)..\"&api_results_limit=\"..textutils.urlEncode(api_results_limit)..\"&api_dev_key=\"..textutils.urlEncode(api_dev_key)..\"&api_option=list\")\
local out=handle.readAll()\
handle.close()\
return out\
end\
\
--[[ Basic Download code --]]\
local function getone(code)\
if type(code)~=\"string\" then error(\"Expected string\",2) end\
handle=http.get(\"http://pastebin.com/raw.php?i=\"..code)\
if not handle then return nil end\
local out=handle.readAll()\
handle.close()\
return out\
end\
\
--[[ Read without any writes() - conceals leanght of password from wiever --]]\
function saferead()\
	term.setCursorBlink( true )\
    local sLine = \"\"\
	local nPos = 0\
	local w, h = term.getSize()\
	local sx, sy = term.getCursorPos()		\
	while true do\
		local sEvent, param = os.pullEvent()\
		if sEvent == \"char\" then\
			sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )\
			nPos = nPos + 1\
		elseif sEvent == \"key\" then\
		    if param == keys.enter then\
				--[[ Enter --]]\
				break\
			elseif param == keys.backspace then\
				--[[ Backspace --]]\
				if nPos > 0 then\
					sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )\
					nPos = nPos - 1		\
				end\
			end\
		end\
	end\
	term.setCursorBlink( false )\
	term.setCursorPos( w + 1, sy )\
	print()\
	return sLine\
end\
\
--[[ PROGRAM START --]]\
\
write(\"Username: \") \
local a=read()\
write(\"Password: \")\
--[[ Passowrd is not stored - is used and forgotten --]]\
api_user_key=login(a,saferead())\
\
--[[ Making user folder next to this program --]]\
dir=fs.combine(dir,a)\
if not fs.exists(dir) then saving(dir) end\
\
--[[ Making public and unlisted folders--]]\
local public=fs.combine(dir,\"public\")\
if not fs.exists(public) then saving(public) end\
local unlisted=fs.combine(dir,\"unlisted\")\
if not fs.exists(unlisted) then saving(unlisted) end\
\
--[[ Getting Filelist containing list of files --]]\
print(\"Downloading Filelist\")\
local pastes=tabulate(listall(api_user_key,tostring(1000)))\
\
--[[ Saving Filelist into a \"code  = name\" list and sorting into tables. Uncomment saving line to save sucessfully. --]]\
local Pastelistpublic={}\
local Pastelistprivate={}\
local Pastelistord={}\
for _,k in pairs(pastes) do\
table.insert((k[\"private\"]==\"0\" and Pastelistpublic) or Pastelistprivate,k[\"key\"]..\" = \"..k[\"title\"])\
end\
table.insert(Pastelistord,\"Public\\n\")\
for _,k in pairs(Pastelistpublic) do table.insert(Pastelistord,k) end\
table.insert(Pastelistord,\"\\nPrivate\\n\") \
for _,k in pairs(Pastelistprivate) do  table.insert(Pastelistord,k)  end\
--[[saving(fs.combine(dir,\"list\"),table.concat(Pastelistord,\"\\n\"))--]]\
\
print(\"Detected \",#Pastelistpublic,\" public pastes and \",#Pastelistprivate,\" private pastes\")\
\
--[[ Selector here.  --]]\
\
\
local offset=0\
local selected=1\
local All=false\
\
local function List()\
local x,y=term.getSize()\
term.clear()\
if #pastes > y-1 then offset=math.max(0,math.min(#pastes-(y-1),selected-math.floor((y-1)/2))) else offset=0 end\
for i=1,math.min(y-1,#pastes) do\
	term.setCursorPos(1,i)\
	if i+offset==selected then\
	term.setTextColour(colours.black)\
	term.setBackgroundColor(colours.white)\
	else\
	term.setTextColour(colours.white)\
	term.setBackgroundColor(colours.black)\
	end\
	local temp=pastes[i+offset]\
	term.write((temp.selected and \"> \" or \"\")..temp[\"title\"]..(temp.selected and \" <\" or \"\"))\
end\
term.setTextColour(colours.white)\
term.setBackgroundColor(colours.black)\
term.setCursorPos(1,y)\
term.write(\"Up/Down,Enter-Sel,D-Download,Tab-D-All\")\
end\
\
List()\
\
while true do\
event= {os.pullEvent()}\
if event[1]==\"key\" then\
	if event[2]==keys.numPadEnter or event[2]==keys.enter then\
		pastes[selected][\"selected\"]=not pastes[selected][\"selected\"]\
		List()\
	elseif event[2]==keys.down then\
		selected=math.min(selected+1,#pastes)\
		List()\
	elseif event[2]==keys.up then\
		selected=math.max(selected-1,1)\
		List()\
	elseif event[2]==keys.d then\
		print()\
		print(\"Downloading Selected\")	\
		break\
	elseif event[2]==keys.tab then\
		print()\
		print(\"Downloading All\")\
		All=true\
		break\
	end\
end --if event\
end\
\
term.setTextColour(colours.white)\
term.setBackgroundColor(colours.black)\
--[[ Download all Selected and place in correct folders  --]]\
for _,k in pairs(pastes) do\
	if k.selected or All then\
		local name=string.gsub(k[\"title\"],\" \",\"_\")\
		local spot=fs.combine((k[\"private\"]==\"0\" and public) or unlisted,name)\
		print(\"Downloading \",(k[\"private\"]==\"0\" and \"public \") or \"unlisted \",k[\"title\"])\
		local file =nil\
		while true do\
			file = getone(k[\"key\"])\
			if file then break end\
			print(\"Failed - Retrying in 5 sec\")\
			sleep(5)\
			print(\"Downloading \",(k[\"private\"]==\"0\" and \"public \") or \"unlisted \",k[\"title\"])\
		end\
		saving(spot,file)\
		print(\"Finished\")\
	end\
end\
\
--[[ If virtualier had pastebin hock call it (using for saving pastes from rom into pendrive-floppy or root ;p) --]]\
if virtual and wojbieGlobalsTable.vfunc.vpastesave then wojbieGlobalsTable.vfunc.vpastesave() end\
\
print(\"All Finished\")"
local pastebinSingle="--[[ File Useage --]]\
local function save(A,B) local file = fs.open(tostring(A),\"w\") file.write(B) file.close() end\
local function saveT(A,B) save(A,textutils.serialize(B)) end\
local function saveTH(A,B) save(A,string.gsub(textutils.serialize(B),\"},\",\"},\\r\\n\")) end\
local function get(A) local file = fs.open(tostring(A),\"r\") if not file then return false end local data = file.readAll() file.close() if data then return data end end\
local function getT(A) local data = get(A) if data then data = textutils.unserialize(data) end if data then return data end end\
\
--[[ Settings --]]\
\
local virtual=false\
local dir=shell.getRunningProgram()\
dir=string.sub(dir,1,#dir-#fs.getName(dir))\
\
--[[ Tests --]]\
\
if not http then\
print(\"I need http Api to be on to work. Sorry.\")\
end\
\
if fs.isReadOnly(shell.getRunningProgram()) then\
	if wojbieGlobalsTable and wojbieGlobalsTable.vfiles and wojbieGlobalsTable.vfunc then\
		virtual=true\
	else\
		print(\"File is in read-only area - can't procced\") return\
	end\
end\
\
--[[ Saving code --]]\
local function saving(A,B)\
	if virtual then\
		wojbieGlobalsTable.vfunc.virtualize(A,B)\
	else\
		if B then save(A,B) else fs.makeDir(A) end\
	end\
end\
\
--[[ Basic Download code --]]\
local function getone(code)\
if type(code)~=\"string\" then error(\"Expected string\",2) end\
handle=http.get(\"http://pastebin.com/raw.php?i=\"..code)\
if not handle then error(\"Wrong Code?\",2)  end\
local out=handle.readAll()\
handle.close()\
return out\
end\
\
--[[ PROGRAM START --]]\
local tArgs={...}\
local a,b\
if tArgs==2 then\
a=tArgs[1]\
b=tArgs[2]\
end\
\
while true do\
write(\"Code: \") a=read()\
if a then break end\
print(\"Need code to download\")\
end\
\
if not b then\
write(\"Savename: \") b=read()\
	if b==\"\" then \
		print(\"No name given - saving using Code\")\
		b=a\
	end\
end\
\
--[[ Making user folder next to this program --]]\
dir=fs.combine(dir,\"Codes\")\
if not fs.exists(dir) then saving(dir) end\
\
--[[ Download and place in correct folder  --]]\
print(\"Downloading \",a,\" Savename: \",b)\
local file =nil\
local limit=0\
file = getone(a)\
if not file then print(\"Incorect Code\") return end\
saving(fs.combine(dir,b),file)\
print(\"Finished\")\
\
--[[ If virtualier had pastebin hock call it (using for saving pastes from rom into pendrive-floppy or root ;p) --]]\
if virtual and wojbieGlobalsTable.vfunc.vpastesave then wojbieGlobalsTable.vfunc.vpastesave() end"
local extrashell="local parentShell = shell\
\
local bExit = false\
local sDir = (parentShell and parentShell.dir()) or \"\"\
local sPath = (parentShell and parentShell.path()) or \".:/rom/programs\"\
local tAliases = (parentShell and parentShell.aliases()) or {}\
local tProgramStack = {}\
local bClock= true\
\
\
local shell = {}\
local tEnv = {\
	[\"shell\"] = shell\
}\
\
--[[ Colours  --]]\
local promptColour, textColour, bgColour\
if term.isColour() then\
	promptColour = colours.yellow\
	textColour = colours.white\
	bgColour = colours.black\
else\
	promptColour = colours.white\
	textColour = colours.white\
	bgColour = colours.black\
end\
\
--[[ File Useage --]]\
local function save(A,B) local file = fs.open(tostring(A),\"w\") file.write(B) file.close() end\
local function saveT(A,B) save(A,textutils.serialize(B)) end\
local function saveTH(A,B) save(A,string.gsub(textutils.serialize(B),\"},\",\"},\\r\\n\")) end\
local function get(A) local file = fs.open(tostring(A),\"r\") if not file then return false end local data = file.readAll() file.close() if data then return data end end\
local function getT(A) local data = get(A) if data then data = textutils.unserialize(data) end if data then return data end end\
\
--[[ Main Functions --]]\
\
local function run( _sCommand, ... )\
	local sPath = shell.resolveProgram( _sCommand )\
	if sPath ~= nil then\
		tProgramStack[#tProgramStack + 1] = sPath\
   		local result = os.run( tEnv, sPath, ... )\
		tProgramStack[#tProgramStack] = nil\
		return result\
   	else\
    	printError( \"No such program\" )\
    	return false\
    end\
end\
\
local LuatEnv = {}\
setmetatable( LuatEnv, { __index = getfenv() } )\
\
local function runlua( _sCommand )\
	if not _sCommand then return false end\
\
\
	local nForcePrint = 0\
	local func, e = loadstring( _sCommand, \"lua\" )\
	local func2, e2 = loadstring( \"return \".._sCommand, \"lua\" )\
	if not func then\
		if func2 then\
			func = func2\
			e = nil\
			nForcePrint = 1\
		end\
	else\
		if func2 then\
			func = func2\
		end\
	end\
	\
	if func then\
        setfenv( func, LuatEnv )\
        local tResults = { pcall( function() return func() end ) }\
        if tResults[1] then\
        	local n = 1\
        	while (tResults[n + 1] ~= nil) or (n <= nForcePrint) do\
        		print( tostring( tResults[n + 1] ) )\
        		n = n + 1\
        	end\
        else\
        	printError( tResults[2] )\
        end\
    else\
    	printError( e )\
    end\
    \
end\
\
local function cat(_Tfiles)\
_,y=term.getSize()\
local out={}\
	for i,k in ipairs(_Tfiles) do\
		local path=shell.resolve(k)\
		if not fs.exists(path) then print(\"File \"..k..\" don't exists\") return end\
		if fs.isDir(path) then print(k..\" is a directory\") return end\
		local file = fs.open(path, \"r\")\
		table.insert(out,file.readAll())\
		file.close()\
	end\
	pcall( function()\
	textutils.pagedPrint(table.concat(out),y)\
	end)\
end\
\
local function findfile(target,patt)\
	if target==\"\" then print(\"No target specified\") return end\
	local matches={}\
	target=string.lower(target)\
	local function process(path)\
		local T=fs.list(path)\
		for _,k in ipairs(T) do\
			local cpath=path..\"/\"..k\
			if string.find(string.lower(k), target , 1 , not patt) then table.insert(matches,cpath) end\
			if fs.isDir(cpath) then process(cpath) end\
		end\
	end\
	\
	local function list(_Tlist)\
		local tFiles = {}\
		local tVFiles = {}\
		local tDirs = {}\
		local tVDirs = {}\
		for n, sItem in pairs(_Tlist) do\
			if wojbieGlobalsTable and wojbieGlobalsTable.vfunc and wojbieGlobalsTable.vfunc.isVirt(sItem) then\
				if fs.isDir( sItem ) then\
					table.insert( tVDirs, sItem )\
				else\
					table.insert( tVFiles, sItem )\
				end\
			else\
				if fs.isDir( sItem ) then\
					table.insert( tDirs, sItem )\
				else\
					table.insert( tFiles, sItem )\
				end\
			end\
		end\
		table.sort( tDirs ) table.sort( tVDirs ) table.sort( tFiles ) table.sort( tVFiles )\
		if term.isColour() then\
			pcall( function()\
			textutils.pagedTabulate( colors.green , tDirs ,colors.lime, tVDirs, colors.white, tFiles, colors.lightGray , tVFiles )\
			end)\
		else\
			pcall( function()\
			textutils.pagedTabulate( tDirs , tVDirs , tFiles , tVFiles)\
			end)\
		end\
	end\
	\
	process(\"\")\
	list(matches)\
end\
\
local function runLine( _sLine )\
	--[[ Standard Execution --]]\
	local tWords = {}\
	for match in string.gmatch( _sLine, \"[^ \\t]+\" ) do\
		table.insert( tWords, match )\
	end\
	local sCommand = tWords[1]\
	if sCommand then\
		return run( sCommand, unpack( tWords, 2 ) )\
	end\
	return false\
end\
\
local function readtab( _sReplaceChar, _tHistory , _sPrefix)\
	term.setCursorBlink( true )\
\
    local sLine = _sPrefix or \"\"\
	local nHistoryPos = nil\
	local nPos = string.len(sLine)\
    if _sReplaceChar then\
		_sReplaceChar = string.sub( _sReplaceChar, 1, 1 )\
	end\
	\
	local w, h = term.getSize()\
	local sx, sy = term.getCursorPos()	\
	local clocvis\
	\
	local function shellclock(_clear)\
		if  bClock and not _clear and sx+#sLine <= w-7 then\
			clocvis=true\
			term.setCursorBlink( false )\
			local state=textutils.formatTime(os.time(),true)\
			while #state<5 do state=\" \"..state end\
			local x=term.getCursorPos()\
			term.setCursorPos( w-5, sy )\
			term.setTextColour( promptColour )\
			write(state)\
			term.setTextColour( textColour )\
			term.setCursorPos( x, sy )\
			term.setCursorBlink( true )\
		else\
			if clocvis then\
				local x=term.getCursorPos()\
				term.setCursorBlink( false )\
				term.setCursorPos( w-5, sy )\
				write(\"     \")\
				term.setCursorPos( x, sy )\
				term.setCursorBlink( true )\
				clocvis=false			\
			end\
		end		\
	end\
	\
	local function redraw( _sCustomReplaceChar )\
		local nScroll = 0\
		if sx + nPos >= w then\
			nScroll = (sx + nPos) - w\
		end\
		shellclock()\
		term.setCursorPos( sx, sy )\
		local sReplace = _sCustomReplaceChar or _sReplaceChar\
		if sReplace then\
			term.write( string.rep( sReplace, string.len(sLine) - nScroll ) )\
		else\
			term.write( string.sub( sLine, nScroll + 1 ) )\
		end\
		term.setCursorPos( sx + nPos - nScroll, sy )\
	end\
\
	local function list(_Tlist,_Spath,_Bhide)\
		shellclock(true)\
		local tFiles = {}\
		local tVFiles = {}\
		local tDirs = {}\
		local tVDirs = {}\
		for n, sItem in pairs(_Tlist) do\
			if not (_Bhide and string.sub( sItem, 1, 1 )==\".\") then\
				local sPath = fs.combine( _Spath, sItem )\
				if wojbieGlobalsTable and wojbieGlobalsTable.vfunc and wojbieGlobalsTable.vfunc.isVirt(sPath) then\
					if fs.isDir( sPath ) then\
						table.insert( tVDirs, sItem )\
					else\
						table.insert( tVFiles, sItem )\
					end\
				else\
					if fs.isDir( sPath ) then\
						table.insert( tDirs, sItem )\
					else\
						table.insert( tFiles, sItem )\
					end\
				end\
			end\
		end\
		table.sort( tDirs ) table.sort( tVDirs ) table.sort( tFiles ) table.sort( tVFiles )\
		print()\
		if term.isColour() then\
			pcall( function()\
			textutils.pagedTabulate( colors.green , tDirs ,colors.lime, tVDirs, colors.white, tFiles, colors.lightGray , tVFiles )\
			end)\
		else\
			pcall( function()\
			textutils.pagedTabulate( tDirs , tVDirs , tFiles , tVFiles)\
			end)\
		end\
		term.setTextColour( promptColour )\
		write( shell.dir() .. \"> \" )\
		term.setTextColour( textColour )\
		sx, sy = term.getCursorPos()\
	end\
	\
	local function common(_String,_Min,_Cur)\
		if not _Cur then return _String end\
		local long=_Cur\
		for i=math.min(#_String,#_Cur),_Min,-1 do\
			local a,b=string.sub (_String,1,i),string.sub(_Cur,1,i)\
			if a==b then return a end		\
		end	\
		return string.sub (_Cur,1,_Min)\
	end\
	\
	local tick\
	if bClock then tick=os.startTimer(1) end\
	redraw()\
	while true do\
		local sEvent, param = os.pullEvent()\
		if sEvent ==\"timer\" and param==tick then shellclock() tick=os.startTimer(1)\
		elseif sEvent == \"char\" then\
			sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )\
			nPos = nPos + 1\
			redraw()\
			\
		elseif sEvent == \"key\" then\
		    if param == keys.enter then\
				--[[ Enter --]]\
				shellclock(true)\
				break\
				\
			elseif param == keys.left then\
				--[[ Left --]]\
				if nPos > 0 then\
					redraw(\" \")\
					nPos = nPos - 1\
					redraw()\
				end\
				\
			elseif param == keys.right then\
				--[[ Right --]]				\
				if nPos < string.len(sLine) then\
					redraw(\" \")\
					nPos = nPos + 1\
					redraw()\
				end\
			\
			elseif param == keys.up or param == keys.down then\
                --[[ Up or down --]]\
				if _tHistory then\
					redraw(\" \")\
					if param == keys.up then\
						--[[ Up --]]\
						if nHistoryPos == nil then\
							if #_tHistory > 0 then\
								nHistoryPos = #_tHistory\
							end\
						elseif nHistoryPos > 1 then\
							nHistoryPos = nHistoryPos - 1\
						end\
					else\
						--[[ Down --]]\
						if nHistoryPos == #_tHistory then\
							nHistoryPos = nil\
						elseif nHistoryPos ~= nil then\
							nHistoryPos = nHistoryPos + 1\
						end						\
					end\
					if nHistoryPos then\
                    	sLine = _tHistory[nHistoryPos]\
                    	nPos = string.len( sLine ) \
                    else\
						sLine = \"\"\
						nPos = 0\
					end\
					redraw()\
                end\
			elseif param == keys.backspace then\
				--[[ Backspace --]]\
				if nPos > 0 then\
					redraw(\" \")\
					sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )\
					nPos = nPos - 1					\
					redraw()\
				end\
			elseif param == keys.home then\
				--[[ Home --]]\
				redraw(\" \")\
				nPos = 0\
				redraw()		\
			elseif param == keys.delete then\
				if nPos < string.len(sLine) then\
					redraw(\" \")\
					sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )				\
					redraw()\
				end\
			elseif param == keys[\"end\"] then\
				--[[ End --]]\
				redraw(\" \")\
				nPos = string.len(sLine)\
				redraw()\
			elseif param == keys.tab and (string.sub( sLine, nPos+1 ,nPos+1)==\" \" or nPos==string.len(sLine)) then\
				--[[ Tab  --]]\
				local need=string.match(string.sub(sLine,1,nPos),\"[ ]?([^ ]-)$\")\
				if need==\"\" or string.match(need,\"[\\\\/]$\") then\
\
					--[[looking at root or /,\\ at end mean folder --]]\
					local path=shell.resolve(need or \"\")\
					if fs.exists(path) and fs.isDir(path) then list(fs.list(path),path,true) end\
					\
				else\
					--[[have part of name --]]					\
					--[[get absolute path and target name --]]\
					local path=\"\"\
					local targ=\"\"\
					if need==\".\" or string.match(need,\"[\\\\/]%.$\") then --[[lokking for hidden in folder --]]\
						path=shell.resolve(need)..\"/\"\
						targ=\".\"\
					else --[[lokking for normal file --]]\
						path=shell.resolve(need)\
						targ=fs.getName(path)\
					end\
					\
					--[[get path without name and see it iteven exists --]]\
					path=string.sub(path,1,#path-#targ) or \"\"\
					if fs.exists(path) and fs.isDir(path) then\
						\
						--[[find files in path matching part --]]\
						--[[at same time look for longest common leading substing --]]\
						local out={}\
						local long=nil\
						local lim=#targ\
						 --[[Sanitizing magic for pattern needs ^$()%.[]*+-?--]]\
						local pattern=\"^\"..string.gsub(string.lower(targ),\"[%^%$%(%)%%%.%[%]%*%+%-%?]\",function(A) return \"%\"..A end)\
						for i,k in pairs(fs.list(path)) do\
							local tempS=string.lower(k)\
							if string.match(tempS,pattern) then\
								table.insert(out,k)\
								long=common(tempS,lim,long)\
							end\
						end\
						if #out==1 then\
							if fs.isDir(fs.combine(path,out[1])) then out[1]=out[1]..\"/\" end\
							sLine=string.sub(sLine,1,nPos-#targ)..out[1]..string.sub( sLine, nPos + 1 )\
							nPos = nPos-#targ+#out[1]\
						elseif #out>1 then\
							sLine=string.sub( sLine, 1, nPos-#targ )..long..string.sub( sLine, nPos + 1 )\
							nPos = nPos-#targ+#long\
							list(out,path)							\
						end	\
					end\
				end\
				redraw()\
			end\
		end\
	end\
	\
	term.setCursorBlink( false )\
	term.setCursorPos( w + 1, sy )\
	print()\
	\
	return sLine\
end\
\
--[[ Install shell API  --]]\
function shell.run( ... )\
	return runLine(table.concat( { ... }, \" \" ))\
end\
\
function shell.exit()\
    bExit = true\
end\
\
function shell.dir()\
	return sDir\
end\
\
function shell.setDir( _sDir )\
	sDir = _sDir\
end\
\
function shell.path()\
	return sPath\
end\
\
function shell.setPath( _sPath )\
	sPath = _sPath\
end\
\
function shell.resolve( _sPath )\
	local sStartChar = string.sub( _sPath, 1, 1 )\
	if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
		return fs.combine( \"\", _sPath )\
	else\
		return fs.combine( sDir, _sPath )\
	end\
end\
\
function shell.resolveProgram( _sCommand )\
	--[[ Substitute aliases firsts  --]]\
	if tAliases[ _sCommand ] ~= nil then\
		_sCommand = tAliases[ _sCommand ]\
	end\
\
    --[[ If the path is a global path, use it directly  --]]\
    local sStartChar = string.sub( _sCommand, 1, 1 )\
    if sStartChar == \"/\" or sStartChar == \"\\\\\" then\
    	local sPath = fs.combine( \"\", _sCommand )\
    	if fs.exists( sPath ) and not fs.isDir( sPath ) then\
			return sPath\
    	end\
		return nil\
    end\
	\
	--[[This line is a security feature i use on \"unsafe\" computers. It basicly stops \"list\" type of malicous code from working directly--]]\
	--[[ Moves . at End of sPath if anywhere in sPath (string.match(sPath, \"^.:\") )--]]\
	--[[if string.match(sPath,\"%.:\") then sPath=string.gsub(sPath,\"%.:\",\"\")..\":.\" end--]]\
	\
 	--[[ Otherwise, look on the path variable  --]]\
    for sPath in string.gmatch(sPath, \"[^:]+\") do\
    	sPath = fs.combine( shell.resolve( sPath ), _sCommand )\
    	if fs.exists( sPath ) and not fs.isDir( sPath ) then\
			return sPath\
    	end\
    end\
	\
	--[[ Not found  --]]\
	return nil\
end\
\
function shell.programs( _bIncludeHidden )\
	local tItems = {}\
	\
	--[[ Add programs from the path  --]]\
    for sPath in string.gmatch(sPath, \"[^:]+\") do\
    	sPath = shell.resolve( sPath )\
		if fs.isDir( sPath ) then\
			local tList = fs.list( sPath )\
			for n,sFile in pairs( tList ) do\
				if not fs.isDir( fs.combine( sPath, sFile ) ) and\
				   (_bIncludeHidden or string.sub( sFile, 1, 1 ) ~= \".\") then\
					tItems[ sFile ] = true\
				end\
			end\
		end\
    end	\
\
	--[[ Sort and return  --]]\
	local tItemList = {}\
	for sItem, b in pairs( tItems ) do\
		table.insert( tItemList, sItem )\
	end\
	table.sort( tItemList )\
	return tItemList\
end\
\
function shell.getRunningProgram()\
	if #tProgramStack > 0 then\
		return tProgramStack[#tProgramStack]\
	end\
	return nil\
end\
\
function shell.setAlias( _sCommand, _sProgram )\
	tAliases[ _sCommand ] = _sProgram\
end\
\
function shell.clearAlias( _sCommand )\
	tAliases[ _sCommand ] = nil\
end\
\
function shell.aliases()\
	--[[ Add aliases  --]]\
	local tCopy = {}\
	for sAlias, sCommand in pairs( tAliases ) do\
		tCopy[sAlias] = sCommand\
	end\
	return tCopy\
end\
	\
term.setBackgroundColor( bgColour )\
term.setTextColour( promptColour )\
print( os.version(), \" Extended\" )\
if wojbieGlobalsTable and wojbieGlobalsTable.vfiles then print(\"Virtual Filesystem is Loaded\") end\
term.setTextColour( textColour )\
\
--[[ If this is the toplevel shell, run the startup programs  --]]\
if parentShell == nil then\
	--[[ Run the startup from the ROM first  --]]\
	local sRomStartup = shell.resolveProgram( \"/rom/startup\" )\
	if sRomStartup then\
		shell.run( sRomStartup )\
	end\
	\
	--[[ Then run the user created startup, from the disks or the root  --]]\
	local sUserStartup = shell.resolveProgram( \"/startup\" )\
	for n,sSide in pairs( peripheral.getNames() ) do\
		if disk.isPresent( sSide ) and disk.hasData( sSide ) then\
			local sDiskStartup = shell.resolveProgram( fs.combine(disk.getMountPath( sSide ), \"startup\") )\
			if sDiskStartup then\
				sUserStartup = sDiskStartup\
				break\
			end\
		end\
	end\
	\
	if sUserStartup then\
		shell.run( sUserStartup )\
	end\
end\
\
--[[ Run any programs passed in as arguments  --]]\
local tArgs = { ... }\
if #tArgs > 0 then\
	shell.run( ... )\
end\
\
--[[ Read commands and execute them -- Most of modyfications happend here  --]]\
local tCommandHistoryfile= (wojbieGlobalsTable and wojbieGlobalsTable.vfunc and wojbieGlobalsTable.vfunc.dir) or \"/\" \
tCommandHistoryfile=fs.combine(tCommandHistoryfile,\".shellhistory.log\")\
local tCommandHistory = {}\
if fs.exists(tCommandHistoryfile) then tCommandHistory = getT(tCommandHistoryfile) or {} end\
local nextprefix = \"\"\
while not bExit do\
	term.setBackgroundColor( bgColour )\
	term.setTextColour( promptColour )\
	write( shell.dir() .. \"> \" )\
	term.setTextColour( textColour )\
	\
	local sLine = readtab( nil, tCommandHistory ,nextprefix)\
	nextprefix = \"\"\
	if sLine~=\"\" then\
	\
		if sLine ~= tCommandHistory[#tCommandHistory] then\
			table.insert( tCommandHistory, sLine )\
			if tCommandHistory[101] then table.remove(tCommandHistory,1) end\
			saveT(tCommandHistoryfile,tCommandHistory)\
		end\
		\
\
		local tWords = {}\
			for match in string.gmatch( sLine, \"[^ \\t]+\" ) do\
			table.insert( tWords, match )\
		end\
		local sCommand = table.remove(tWords,1)\
		\
		if sCommand == \"lua<\" then --[[ Lua Execution --]]\
			runlua( string.sub( sLine, 6) )\
			nextprefix = \"lua< \"\
		elseif sCommand == \"lua#\" then --[[ Lua Clear --]]\
			LuatEnv = {} setmetatable( LuatEnv, { __index = getfenv() } ) print(\"Shell Lua Enviroment Cleared\")\
		elseif sCommand == \"cat<\" then	--[[ Cat Execution --]]\
			cat(tWords)	\
		elseif sCommand == \"clock<\" then	--[[ Clock Toggle --]]\
			bClock=not bClock print(\"Clock \",(bClock and \"On\")or\"Off\")\
		elseif sCommand == \"find<\" then	--[[ Find Execution --]]\
			findfile(string.sub( sLine, 7))\
		elseif sCommand == \"findpattern<\" then	--[[ Find with pattern Execution --]]\
			findfile(string.sub( sLine, 14),true)\
		elseif sCommand == \"help<\" or sCommand == \"?<\"  then	--[[ HElp Execution --]]\
			print(\"List of extra shell commands: lua<,lua#,cat<,clock<,find<,findpattern<,help<\")\
		elseif sCommand then --[[ Standard Execution --]]\
			run( sCommand, unpack( tWords ) )\
		end\
	end	\
end\
\
--[[ If this is the toplevel shell, run the shutdown program  --]]\
if parentShell == nil then\
	if shell.resolveProgram( \"shutdown\" ) then\
		shell.run( \"shutdown\" )\
	end\
	os.shutdown() --[[ just in case  --]]\
end\
\
term.setTextColour( promptColour )\
print(\"Extended Shell Terminated\")\
term.setTextColour( textColour )"

local editmark="load%(sPath%)"
local editover="load(sPath)\nscrollY=tonumber(tArgs[2]) or scrollY\nscrollY=math.floor(math.max(0,math.min(scrollY-1,#tLines)))\ny=tonumber(tArgs[2]) or y\ny=math.floor(math.max(1,math.min(y,#tLines)))"

--[[
--loading from side files code ;p for easier debugging of programs
local function loadInSystem(A,B)
--local temp=string.gsub(textutils.serialize(get(fs.combine(dir,A))), "\\\n" , " "  )
local temp=textutils.serialize(get(fs.combine(dir,A)))
if B then save(fs.combine(dir,"flat"..A),temp) end
return loadstring("return "..temp)()
end

list=loadInSystem("list.lua",true)
pastebinLogin=loadInSystem("UserGet.lua",true)
pastebinSingle=loadInSystem("singleFile.lua",true)
extrashell=loadInSystem("shell.lua",true)
--]]

--help data
help=" \n \nYou are using Extended Shell By Wojbie\nType \"help shellExt\" for help with additional features"
help2="Additional features of Extended Shell are:\
 \
  1) You can press Tab to auto-complete commands. If there are more than one match it will print all of them\
 \
  2) By typing \"lua<\" followed by lua code you can call lua functions from shell. Type \"lua#\" to reset enviroment (removes all stuff you defined)\
 \
  3) Shell History - Last 100 commeneds that you called are stored in shell log file. That means they will be tere even after restet. \
 \
 4) Virtualized files! This allows me to mess with contents of rom. Without realy messing with it. Virtual acces Api is in WIP\
 \
  5) \"vpastebin\" folder in rom allows you to keep all of your pastes. Using \"login\" you can safely download all of your pastes. After that they will all be in foler of your Username. Using \"single\" downloads single paste and places it in \"codes\" folder.\
 \
  6) Additional Colors!! in colored mode list is colorcoded. Real folders are green / virtual are lime. Real files are white / virtual are lightgray\
 \
  7) Super Extra Clock in active line!!\
  \
  8) Whole Shell is written to allow live use. If placed anywhere not in rom it will store pastes and hostory in hidden files next to it. That allows you to heep in of floppy and take with you everywhere.!"

--saving normal functions

local oldfiles=fs

--Utility Functions

local function getone(code)
if type(code)~="string" then return "print(\"Wrong Code in .vfsprograms.dat\")" end
handle=http.get("http://pastebin.com/raw.php?i="..code)
if not handle then return "print(\"Wrong Code in .vfsprograms.dat\")"  end
local out=handle.readAll()
handle.close()
return out or "print(\"Wrong Code in .vfsprograms.dat\")"
end

local function part(A) --A String with path
	local out={}
	--if string.find (A,"[\\/][\\/]") then return out end
	--for i in string.gmatch (A,"([a-zA-Z0-9._-]+)[\\/]?") do --old idea
	for i in string.gmatch (A,"([^\\/]+)[\\/]*") do --better idea
		table.insert (out,i)
	end
	return out
end

local function reach(A,B) -- A table from part() or string to send to part(),B - return cont and last part of A
if type(A)=="string" then A=part(A) end
local point=wojbieGlobalsTable.vfiles
local cont,concon=nil,nil
for i in ipairs(A) do
if A~="." then
	if A==".." then
	point=cont
	cont=concon
	else
		if not point[A[i]] then return nil end
		concon=cont
		cont=point
		point=point[A[i]]
	end
end
end
return point,(B and cont),(B and A[#A])
end

local function vinoSave(A,B) --saves virtualized file into normal file ( works on directores requrency)
if fs.exists(A) then error("File exists",2) end	
	if type(B)=="table" then
		fs.makeDir(A)
		for i,k in pairs(B) do vinoSave(fs.combine(A,i),k) end
	elseif type(B)=="string" then
		save(A,B)
	end
end

local function virtualize(A,B) --A table to virtualize from part(A),optional B - contents of last part. If left empty makes a directory
if type(A)=="string" then A=part(A) end
local point=wojbieGlobalsTable.vfiles
local cont=nil
for i in ipairs(A) do
	if not point[A[i]] then
		point[A[i]]={}
	end
	cont=point
	point=point[A[i]]
end
if B then cont[A[#A]]=B end
end

local function isVirt(A)
return reach(A) and not oldfiles.exists(A)
end

local function isBoth(A)
return reach(A) and oldfiles.exists(A)
end

local function vpastesave()
saveT(fs.combine(dir,".vfssavedpastes.dat"),reach("/rom/vpastebin"))
end

--adding selected functions to global table.

wojbieGlobalsTable.vfunc.isVirt=isVirt
wojbieGlobalsTable.vfunc.virtualize=virtualize
wojbieGlobalsTable.vfunc.vpastesave=vpastesave

--creating filesystem

virtualize("/rom/programs/list",list) --virtualizes contents of list program into rom

if fs.exists(fs.combine(dir,".vfssavedpastes.dat")) then virtualize("/rom/vpastebin",getT(fs.combine(dir,".vfssavedpastes.dat"))) end
virtualize("/rom/vpastebin/login",pastebinLogin) --virtualizes login and creates pasts in rom into rom/ also loads pastes if any saved
virtualize("/rom/vpastebin/single",pastebinSingle) --virtualizes login and creates pasts in rom into rom/ also loads pastes if any saved

virtualize("/rom/programs/shell",extrashell) --virtualizes shell into rom
virtualize("/rom/programs/Wojbie","print(\"Wojbie Rulez\")")

-- patching files
virtualize("/rom/programs/edit",string.gsub(get("/rom/programs/edit"), editmark, editover ))  --virtualizes and patches edit into rom

--loading side programs into rom/programs

if fs.exists(fs.combine(dir,".vfsprograms.dat")) then
	local Toload=get(fs.combine(dir,".vfsprograms.dat"))or""
	local sideprograms=getT(fs.combine(dir,".vfsprogramsLib.dat"))or{}
	local tosave=false
	for i,k in string.gmatch(Toload,"([%w]+)=([%w]+)") do
		if i and k then
			if not sideprograms[i] and http then
				print("Downloading Missing program ",k," from ",i)
				sideprograms[i]=getone(i)
				tosave=true
				print("Finished")
			end
			virtualize(fs.combine("/rom/programs/",k),sideprograms[i])
		end
	end
	if tosave then saveT(fs.combine(dir,".vfsprogramsLib.dat"),sideprograms) end
else
save(fs.combine(dir,".vfsprograms.dat"),"")
end

--creating help topics

virtualize("/rom/help/shell",get("/rom/help/shell")..help)
virtualize("/rom/help/shellExt",help2)

--[[
--large folder for testing shell
for i=1,1000 do
virtualize("/test/"..i,"print(\""..i.."\")")
end
--]]

--Overwrite Functions

_G["fs"]={

--no changes in those
isReadOnly = oldfiles.isReadOnly,
getName = oldfiles.getName,
getFreeSpace= oldfiles.getFreeSpace,
makeDir=oldfiles.makeDir,
combine= oldfiles.combine,

--simple return logic
exists = function(A) return (reach(A) and true) or oldfiles.exists(A) end,
isDir = function(A) return type(reach(A))=="table" or oldfiles.isDir(A) end,
getSize=function(A)	return (oldfiles.exists(A) and oldfiles.getSize(A)) or (reach(A) and 0) or oldfiles.getSize(A) end,

--longer logic
list = function(A)
	local out=(oldfiles.exists(A) and oldfiles.isDir(A) and oldfiles.list(A)) or {}
	local cur=reach(A)
	if type(cur)=="table" then
		for i,k in pairs(cur) do
			local over=true
			for j,_ in pairs(out) do
				if out[j]==i then over=false break end
			end
			if over then table.insert(out,i) end
		end
	end
	return out
end,


getDrive = function(A)
	local path=part(A)
	if (reach(path)) then
	while #path>0 do
		local temp=oldfiles.getDrive(table.concat(path,"/"))
		table.remove(path)
		if temp then return temp end
	end
	return "hdd"
	else
		return oldfiles.getDrive(A)
	end
end,

copy=function(A,B)
	if type(A)~="string" or type(B)~="string" then error("Expected string, string",2) end
	if not fs.exists(A) then error("No such file",2) 
	elseif fs.isReadOnly(B) then error("Access denied",2)
    elseif fs.exists(B) then error("File exists",2) end	
	
	local pointA=reach(A)
	local pointB=reach(part(B))
	if pointB then --from x to virtual - nope you need to use api for that
	error("Access denied",2)
	elseif pointA then --from virtual to normal - ok!
	assert(vinoSave,"Copy failed")(B,pointA)
	else --from normal to normal
	oldfiles.copy(A,B)
	end
end,

delete=function (A)
	if type(A)~="string" then error("Expected string",2) end 
	local vfile,vcont,vname=reach(A,true)
	if fs.isReadOnly(A) then error("Access denied",2) end
	if vfile then --virtual file is delete if exists 
	vcont[vname]=nil
	else --normal file delete if virtual don't exists
	oldfiles.delete(A)
	end
end,

move=function(A,B) fs.copy(A,B)	fs.delete(A) end,

open=function(A,B)
	--This is gonna be longer part to write - need to code creation of handle that 'handles' virtual files ;)
	--for now only handles reading from virtual files - all saving will return nil.
	local vfile,vcont,vname=reach(A,true)
	if vfile and type(vfile)~="table" then
		if B=="r" then
		
			local handle={}
			local data=vfile
			local open=true
			
			function handle.readLine()
				if not open then return nil end
				local out,cut=string.match(data,"([^\r\n]+)[\r\n]*()")
				if cut then data=string.sub(data,cut) end
				return out
			end
			
			function handle.readAll()
				if not open then return nil end
				local out=nil
				if data~="" then out=data end
				data=""
				return out
			end
			
			function handle.close()
				data=""
				open=false
			end
			
			return handle
			
		elseif B=="w" or B=="a" then  -- overwrtiting/appending virtual file
		
			local handle={}
			local data=(B=="w" and "") or (B=="a" and cond)
			local container=vcont
			local target=vname
			local open=true
			
			function handle.write(A)
				if not open then return end
				data=data..A
			end
			
			function handle.writeLine(A)
				if not open then return end
				data=data..A.."\n"
			end
			
			function handle.flush()
				if not open then return end
				container[target]=data
			end
			
			function handle.close()
				container[target]=data
				data=""
				open=false
			end
			
			return handle

		else-- mode not implemented. This is for binary and stuff
			return nil
		end
	else	
		return oldfiles.open(A,B)
	end
end,
}

--Starting MOdyfied Shell
term.clear()
term.setCursorPos(1,1)
local ok, param =pcall( function() os.run({["shell"] = shell,}, "/rom/programs/shell" , unpack(tArg) ) end )
--Cleanup and return to basic shell
_G["fs"]=oldfiles
wojbieGlobalsTable.vfiles=nil
wojbieGlobalsTable.vfunc=nil
print("Thank You For Using Wojbie's extended Shell and Utilites.")
print("Virtual Files Unloaded")
if not ok then printError( param ) end
else --Attemting to run program again? run shell instead!!
os.run({["shell"] = shell,}, "/rom/programs/shell" , unpack(tArg) )
end