ccpt/ccpt
2021-06-01 11:25:04 +02:00

1000 lines
30 KiB
Lua

--[[
ComputerCraft Package Tool
Author: PentagonLP
Version: 1.0
Lines of Code: 1.000; Characters: 30.485
]]
-- Load properprint library
os.loadAPI("lib/properprint")
-- Read arguments
args = {...}
-- Link to a list of packages that are present by default (used in 'update()')
defaultpackageurl = "https://raw.githubusercontent.com/PentagonLP/ccpt/main/defaultpackages.ccpt"
-- Counters to print out at the very end
installed = 0
updated = 0
removed = 0
-- FILE MANIPULATION FUNCTIONS --
--[[ Checks if file exists
@param String filepath: Filepath to check
@return boolean: Does the file exist?
--]]
function file_exists(filepath)
local f=io.open(filepath,"r")
if f~=nil then
io.close(f)
return true
else
return false
end
end
--[[ Stores a file in a desired location
@param String filepath: Filepath where to create file (if file already exists, it gets overwritten)
@param String content: Content to store in file
--]]
function storeFile(filepath,content)
writefile = fs.open(filepath,"w")
writefile.write(content)
writefile.close()
end
--[[ Reads a file from a desired location
@param String filepath: Filepath to the file to read
@param String createnew: (Optional) Content to store in new file and return if file does not exist. Can be nil.
@return String|boolean content|error: Content of the file; If createnew is nil and file doesn't exist boolean false is returned
--]]
function readFile(filepath,createnew)
readfile = fs.open(filepath,"r")
if readfile == nil then
if not (createnew==nil) then
storeFile(filepath,createnew)
return createnew
else
return false
end
end
content = readfile.readAll()
readfile.close()
return content
end
--[[ Stores a table in a file
@param String filepath: Filepath where to create file (if file already exists, it gets overwritten)
@param Table data: Table to store in file
--]]
function storeData(filepath,data)
storeFile(filepath,textutils.serialize(data):gsub("\n",""))
end
--[[ Reads a table from a file in a desired location
@param String filepath: Filepath to the file to read
@param boolean createnew: If true, an empty table is stored in new file and returned if file does not exist.
@return Table|boolean content|error: Table thats stored in the file; If createnew is false and file doesn't exist boolean false is returned
--]]
function readData(filepath,createnew)
if createnew then
return textutils.unserialize(readFile(filepath,textutils.serialize({}):gsub("\n","")))
else
return textutils.unserialize(readFile(filepath,nil))
end
end
-- HTTP FETCH FUNCTIONS --
--[[ Gets result of HTTP URL
@param String url: The desired URL
@return Table|boolean result|error: The result of the request; If the URL is not reachable, an error is printed in the terminal and boolean false is returned
--]]
function gethttpresult(url)
if not http.checkURL(defaultpackageurl) then
properprint.pprint("ERROR: Url '" .. url .. "' is blocked in config. Unable to fetch data.")
return false
end
result = http.get(url)
if result == nil then
properprint.pprint("ERROR: Unable to reach '" .. url .. "'")
return false
end
return result
end
--[[ Gets table from HTTP URL
@param String url: The desired URL
@return Table|boolean result|error: The content of the site parsed into a table; If the URL is not reachable, an error is printed in the terminal and boolean false is returned
--]]
function gethttpdata(url)
result = gethttpresult(url)
if result == false then
return false
end
data = result.readAll()
data = string.gsub(data,"\n","")
return textutils.unserialize(data)
end
--[[ Download file HTTP URL
@param String filepath: Filepath where to create file (if file already exists, it gets overwritten)
@param String url: The desired URL
@return nil|boolean nil|error: nil; If the URL is not reachable, an error is printed in the terminal and boolean false is returned
--]]
function downloadfile(filepath,url)
result = gethttpresult(url)
if result == false then
return false
end
storeFile(filepath,result.readAll())
end
-- PACKAGE FUNCTIONS --
--[[ Checks wether a package is installed
@param String packageid: The ID of the package
@return boolean installed: Is the package installed?
]]--
function isinstalled(packageid)
return not (readData("/.ccpt/installedpackages",true)[packageid] == nil)
end
--[[ Checks wether a package is installed
@param String packageid: The ID of the package
@return Table|boolean packagedata|error: Read the data of the package from '/.ccpt/packagedata'; If package is not found return false
]]--
function getpackagedata(packageid)
-- Read package data
allpackagedata = readData("/.ccpt/packagedata",false)
-- Is the package data built yet?
if allpackagedata==false then
properprint.pprint("Package Date is not yet built. Please execute 'ccpt update' first. If this message still apears, thats a bug, please report.")
return false
end
packagedata = allpackagedata[packageid]
-- Does the package exist?
if packagedata==nil then
properprint.pprint("No data about package '" .. packageid .. "' availible. If you've spelled everything correctly, try executing 'ccpt update'")
return false
end
-- Is the package installed?
installedversion = readData("/.ccpt/installedpackages",true)[packageid]
if not (installedversion==nil) then
packagedata["status"] = "installed"
packagedata["installedversion"] = installedversion
else
packagedata["status"] = "not installed"
end
return packagedata
end
--[[ Searches all packages for updates
@param Table|nil installedpackages|nil: installedpackages to prevent fetching them again; If nil they are fetched again
@param boolean|nil reducedprint|nil: If reducedprint is true, only if updates are availible only the result is printed in console, but nothing else. If nil, false is taken as default.
@result Table packageswithupdates: Table with packages with updates is returned
]]--
function checkforupdates(installedpackages,reducedprint)
-- If parameters are nil, load defaults
reducedprint = reducedprint or false
installedpackages = installedpackages or readData("/.ccpt/installedpackages",true)
bprint("Checking for updates...",reducedprint)
-- Check for updates
packageswithupdates = {}
for k,v in pairs(installedpackages) do
if getpackagedata(k)["newestversion"] > v then
packageswithupdates[#packageswithupdates+1] = k
end
end
-- Print result
if #packageswithupdates==0 then
bprint("All installed packages are up to date!",reducedprint)
elseif #packageswithupdates==1 then
print("There is 1 package with a newer version availible: " .. arraytostring(packageswithupdates))
else
print("There are " .. #packageswithupdates .." packages with a newer version availible: " .. arraytostring(packageswithupdates))
end
return packageswithupdates
end
-- MISC HELPER FUNCTIONS --
--[[ Checks wether a String starts with another one
@param String haystack: String to check wether is starts with another one
@param String needle: String to check wether another one starts with it
@return boolean result: Wether the firest String starts with the second one
]]--
function startsWith(haystack,needle)
return string.sub(haystack,1,string.len(needle))==needle
end
--[[ Presents a choice in console to wich the user can anser with 'y' ('yes') or 'n' ('no'). Captialisation doesn't matter.
@return boolean choice: The users choice
]]--
function ynchoice()
while true do
input = io.read()
if (input=="y") or (input == "Y") then
return true
elseif (input=="n") or (input == "N") then
return false
else
print("Invalid input! Please use 'y' or 'n':")
end
end
end
--[[ Prints only if a given boolean is 'false'
@param String text: Text to print
@param boolean booleantocheck: Boolean wether not to print
]]--
function bprint(text, booleantocheck)
if not booleantocheck then
properprint.pprint(text)
end
end
--[[ Converts an array to a String; array entrys are split with spaces
@param Table array: The array to convert
@param boolean|nil iterator|nil: If true, not the content but the address of the content within the array is converted to a string
@return String convertedstring: The String biult from the array
]]--
function arraytostring(array,iterator)
iterator = iterator or false
result = ""
if iterator then
for k,v in pairs(array) do
result = result .. k .. " "
end
else
for k,v in pairs(array) do
result = result .. v .. " "
end
end
return result
end
-- COMMAND FUNCTIONS --
-- Update
--[[ Get packageinfo from the internet and search from updates
@param boolean startup: Run with startup=true on computer startup; if startup=true it doesn't print as much to the console
]]--
function update(startup)
startup = startup or false
-- Fetch default Packages
bprint("Fetching Default Packages...",startup)
packages = gethttpdata(defaultpackageurl)["packages"]
if defaultpackages==false then
return
end
-- Load custom packages
bprint("Reading Custom packages...",startup)
custompackages = readData("/.ccpt/custompackages",true)
-- Add Custom Packages to overall package list
for k,v in pairs(custompackages) do
packages[k] = v
end
-- Fetch package data from the diffrent websites
packagedata = {}
for k,v in pairs(packages) do
bprint("Downloading package data of '" .. k .. "'...",startup)
packageinfo = gethttpdata(v)
if not (packageinfo==false) then
packagedata[k] = packageinfo
else
properprint.pprint("Failed to retrieve data about '" .. k .. "' via '" .. v .. "'. Skipping this package.")
end
end
bprint("Storing package data of all packages...",startup)
storeData("/.ccpt/packagedata",packagedata)
-- Read installed packages
bprint("Reading Installed Packages...",startup)
installedpackages = readData("/.ccpt/installedpackages",true)
bprint("Data update complete!",startup)
-- Check for updates
checkforupdates(installedpackages,startup)
end
-- Install
--[[ Install a Package
]]--
function install()
if args[2] == nil then
properprint.pprint("Incomplete command, missing: 'Package ID'; Syntax: 'ccpt install <PackageID>'")
return
end
packageinfo = getpackagedata(args[2])
if packageinfo == false then
return
end
if packageinfo["status"] == "installed" then
properprint.pprint("Package '" .. args[2] .. "' is already installed.")
return
end
-- Ok, all clear, lets get installing!
result = installpackage(args[2],packageinfo)
if result==false then
return
end
print("Install of '" .. args[2] .. "' complete!")
end
--[[ Recursive function to install Packages and dependencies
]]--
function installpackage(packageid,packageinfo)
properprint.pprint("Installing '" .. packageid .. "'...")
-- Get Packageinfo
if (packageinfo==nil) then
print("Reading packageinfo of '" .. packageid .. "'...")
packageinfo = getpackagedata(packageid)
if packageinfo==false then
return false
end
end
-- Install dependencies
properprint.pprint("Installing dependencies of '" .. packageid .. "', if there are any...")
for k,v in pairs(packageinfo["dependencies"]) do
installedpackages = readData("/.ccpt/installedpackages",true)
if installedpackages[k] == nil then
if installpackage(k,nil)==false then
return false
end
elseif installedpackages[k] < v then
if upgradepackage(k,nil)==false then
return false
end
end
end
-- Install package
print("Installing '" .. packageid .. "'...")
installdata = packageinfo["install"]
result = installtypes[installdata["type"]]["install"](installdata)
if result==false then
return false
end
installedpackages = readData("/.ccpt/installedpackages",true)
installedpackages[packageid] = packageinfo["newestversion"]
storeData("/.ccpt/installedpackages",installedpackages)
print("'" .. packageid .. "' successfully installed!")
installed = installed+1
end
--[[ Different install methodes
]]--
function installlibrary(installdata)
result = downloadfile("lib/" .. installdata["filename"],installdata["url"])
if result==false then
return false
end
end
function installscript(installdata)
result = downloadfile("/.ccpt/tempinstaller",installdata["scripturl"])
if result==false then
return false
end
shell.run("/.ccpt/tempinstaller","install")
fs.delete("/.ccpt/tempinstaller")
end
-- Upgrade
-- Upgrade installed Packages
-- TODO: Single package updates
function upgrade()
packageswithupdates = checkforupdates(readData("/.ccpt/installedpackages",true),false)
if packageswithupdates==false then
return
end
if #packageswithupdates==0 then
return
end
properprint.pprint("Do you want to update these packages? [y/n]:")
if not ynchoice() then
return
end
for k,v in pairs(packageswithupdates) do
upgradepackage(v,nil)
end
end
--[[ Recursive function to update Packages and dependencies
]]--
function upgradepackage(packageid,packageinfo)
-- Get Packageinfo
if (packageinfo==nil) then
print("Reading packageinfo of '" .. packageid .. "'...")
packageinfo = getpackagedata(packageid)
if packageinfo==false then
return false
end
end
installedpackages = readData("/.ccpt/installedpackages",true)
if installedpackages==packageinfo["newestversion"] then
properprint.pprint("'" .. packageid .. "' already updated! Skipping... (This is NOT an error)")
else
properprint.pprint("Updating '" .. packageid .. "' (" .. installedpackages[packageid] .. "->" .. packageinfo["newestversion"] .. ")...")
end
-- Install/Update dependencies
properprint.pprint("Updating or installing new dependencies of '" .. packageid .. "', if there are any...")
for k,v in pairs(packageinfo["dependencies"]) do
installedpackages = readData("/.ccpt/installedpackages",true)
if installedpackages[k] == nil then
if installpackage(k,nil)==false then
return false
end
elseif installedpackages[k] < v then
if upgradepackage(k,nil)==false then
return false
end
end
end
-- Install package
print("Updating '" .. packageid .. "'...")
installdata = packageinfo["install"]
result = installtypes[installdata["type"]]["update"](installdata)
if result==false then
return false
end
installedpackages = readData("/.ccpt/installedpackages",true)
installedpackages[packageid] = packageinfo["newestversion"]
storeData("/.ccpt/installedpackages",installedpackages)
print("'" .. packageid .. "' successfully updated!")
updated = updated+1
end
--[[ Different install methodes require different update methodes
]]--
function updatescript(installdata)
result = downloadfile("/.ccpt/tempinstaller",installdata["scripturl"])
if result==false then
return false
end
shell.run("/.ccpt/tempinstaller","update")
fs.delete("/.ccpt/tempinstaller")
end
-- Uninstall
-- Remove installed Packages
function uninstall()
-- Check input
if args[2] == nil then
properprint.pprint("Incomplete command, missing: 'Package ID'; Syntax: 'ccpt uninstall <PackageID>'")
return
end
packageinfo = getpackagedata(args[2])
if packageinfo == false then
return
end
if packageinfo["status"] == "not installed" then
properprint.pprint("Package '" .. args[2] .. "' is not installed.")
return
end
-- Check witch package(s) to remove (A package dependend on a package that's about to get removed is also removed)
packagestoremove = getpackagestoremove(args[2],packageinfo,readData("/.ccpt/installedpackages",true),{})
packagestoremovestring = ""
for k,v in pairs(packagestoremove) do
if not (k==args[2]) then
packagestoremovestring = packagestoremovestring .. k .. " "
end
end
-- Are you really really REALLY sure to remove these packages?
if not (#packagestoremovestring==0) then
properprint.pprint("There are installed packages that depend on the package you want to uninstall: " .. packagestoremovestring)
properprint.pprint("These packages will be removed if you proceed. Are you sure you want to continue? [y/n]:")
if ynchoice() == false then
return
end
else
properprint.pprint("There are no installed packages that depend on the package you want to uninstall.")
properprint.pprint("'" .. args[2] .. "' will be removed if you proceed. Are you sure you want to continue? [y/n]:")
if ynchoice() == false then
return
end
end
-- If cctp would be removed in the process, tell the user that that's a dump idea. But I mean, who am I to stop him, I guess...
for k,v in pairs(packagestoremove) do
if k=="ccpt" then
if args[2] == "ccpt" then
properprint.pprint("You are about to uninstall the package tool itself. You won't be able to install or uninstall stuff using the tool afterwords (obviously). Are you sure you want to continue? [y/n]:")
else
properprint.pprint("You are about to uninstall the package tool itself, because it depends one or more package that is removed. You won't be able to install or uninstall stuff using the tool afterwords (obviously). Are you sure you want to continue? [y/n]:")
end
if ynchoice() == false then
return
end
break
end
end
-- Uninstall package(s)
for k,v in pairs(packagestoremove) do
print("Uninstalling '" .. k .. "'...")
installdata = getpackagedata(k)["install"]
result = installtypes[installdata["type"]]["remove"](installdata)
if result==false then
return false
end
installedpackages = readData("/.ccpt/installedpackages",true)
installedpackages[k] = nil
storeData("/.ccpt/installedpackages",installedpackages)
print("'" .. k .. "' successfully uninstalled!")
removed = removed+1
end
end
--[[ Recursive function to find all Packages that are dependend on the one we want to remove to also remove them
]]--
function getpackagestoremove(packageid,packageinfo,installedpackages,packagestoremove)
packagestoremove[packageid] = true
-- Get Packageinfo
if (packageinfo==nil) then
print("Reading packageinfo of '" .. packageid .. "'...")
packageinfo = getpackagedata(packageid)
if packageinfo==false then
return false
end
end
-- Check packages that are dependend on that said package
for k,v in pairs(installedpackages) do
if not (getpackagedata(k)["dependencies"][packageid]==nil) then
packagestoremovenew = getpackagestoremove(k,nil,installedpackages,packagestoremove)
for l,w in pairs(packagestoremovenew) do
packagestoremove[l] = true
end
end
end
return packagestoremove
end
--[[ Different install methodes require different uninstall methodes
]]--
function removelibrary(installdata)
fs.delete("lib/" .. installdata["filename"])
end
function removescript(installdata)
result = downloadfile("/.ccpt/tempinstaller",installdata["scripturl"])
if result==false then
return false
end
shell.run("/.ccpt/tempinstaller","remove")
fs.delete("/.ccpt/tempinstaller")
end
-- Add
--[[ Add custom package URL to local list
]]--
function add()
-- Check input
if args[2] == nil then
properprint.pprint("Incomplete command, missing: 'Package ID'; Syntax: 'ccpt add <PackageID> <PackageinfoURL>'")
return
end
if args[3] == nil then
properprint.pprint("Incomplete command, missing: 'Packageinfo URL'; Syntax: 'ccpt add <PackageID> <PackageinfoURL>'")
return
end
custompackages = readData("/.ccpt/custompackages",true)
if not (custompackages[args[2]]==nil) then
properprint.pprint("A custom package with the id '" .. args[2] .. "' already exists! Please choose a different one.")
return
end
if not file_exists("/.ccpt/packagedata") then
properprint.pprint("Package Date is not yet built. Please execute 'ccpt update' first. If this message still apears, thats a bug, please report.")
end
-- Overwrite default packages?
if not (readData("/.ccpt/packagedata",true)[args[2]]==nil) then
properprint.pprint("A package with the id '" .. args[2] .. "' already exists! This package will be overwritten if you proceed. Do you want to proceed? [y/n]:")
if not ynchoice() then
return
end
end
-- Add entry in custompackages file
custompackages[args[2]] = args[3]
storeData("/.ccpt/custompackages",custompackages)
properprint.pprint("Custom package successfully added!")
-- Update packagedata?
properprint.pprint("Do you want to update the package data ('cctp update')? Your custom package won't be able to be installed until updating. [y/n]:")
if ynchoice() then
update()
end
end
-- Remove
--[[ Remove Package URL from local list
]]--
function remove()
-- Check input
if args[2] == nil then
properprint.pprint("Incomplete command, missing: 'Package ID'; Syntax: 'ccpt remove <PackageID>'")
return
end
custompackages = readData("/.ccpt/custompackages",true)
if custompackages[args[2]]==nil then
properprint.pprint("A custom package with the id '" .. args[2] .. "' does not exist!")
return
end
-- Really wanna do that?
properprint.pprint("Do you want to remove the custom package '" .. args[2] .. "'? There is no undo. [y/n]:")
if not ynchoice() then
properprint.pprint("Canceled. No action was taken.")
return
end
-- Remove entry from custompackages file
custompackages[args[2]] = nil
storeData("/.ccpt/custompackages",custompackages)
properprint.pprint("Custom package successfully removed!")
-- Update packagedata?
properprint.pprint("Do you want to update the package data ('cctp update')? Your custom package will still be able to be installed/updated/uninstalled until updating. [y/n]:")
if ynchoice() then
update()
end
end
-- Info
--[[ Info about a package
]]--
function info()
-- Check input
if args[2] == nil then
properprint.pprint("Incomplete command, missing: 'Package ID'; Syntax: 'ccpt info <PackageID>'")
return
end
-- Get packagedata
packageinfo = getpackagedata(args[2])
if packageinfo == false then
return
end
-- Print packagedata
properprint.pprint(packageinfo["name"] .. " by " .. packageinfo["author"])
properprint.pprint(packageinfo["comment"])
if not (packageinfo["website"]==nil) then
properprint.pprint("Website: " .. packageinfo["website"])
end
properprint.pprint("Installation Type: " .. installtypes[packageinfo["install"]["type"]]["desc"])
if packageinfo["status"]=="installed" then
properprint.pprint("Installed, Version: " .. packageinfo["installedversion"] .. "; Newest Version is " .. packageinfo["newestversion"])
else
properprint.pprint("Not installed; Newest Version is " .. packageinfo["newestversion"])
end
end
-- List
--[[ List all Packages
]]--
function list()
-- Read data
print("Reading all packages data...")
if not file_exists("/.ccpt/packagedata") then
properprint.pprint("No Packages found. Please run 'cctp update' first.'")
return
end
packagedata = readData("/.ccpt/packagedata",true)
print("Reading Installed packages...")
installedpackages = readData("/.ccpt/installedpackages",true)
-- Print list
properprint.pprint("List of all known Packages:")
for k,v in pairs(installedpackages) do
if packagedata[k]["newestversion"] > v then
updateinfo = "outdated"
else
updateinfo = "up to date"
end
properprint.pprint(k .. " (installed, " .. updateinfo .. ")",2)
end
for k,v in pairs(packagedata) do
if installedpackages[k] == nil then
properprint.pprint(k .. " (not installed)",2)
end
end
end
-- Startup
--[[ Run on Startup
]]--
function startup()
-- Update silently on startup
update(true)
end
-- Help
--[[ Print help
]]--
function help()
print("Syntax: ccpt")
for i,v in pairs(actions) do
if (not (v["comment"] == nil)) then
properprint.pprint(i .. ": " .. v["comment"],5)
end
end
print("")
print("This package tool has Super Creeper Powers.")
end
-- Version
--[[ Print Version
]]--
function version()
-- Count lines
linecount = 0
for _ in io.lines'ccpt' do
linecount = linecount + 1
end
-- Print version
properprint.pprint("ComputerCraft Package Tool")
properprint.pprint("by PentagonLP")
properprint.pprint("Version: 1.0")
properprint.pprint(linecount .. " lines of code containing " .. #readFile("ccpt",nil) .. " Characters.")
end
-- Idk randomly appeared one day
--[[ Fuse
]]--
function zzzzzz()
properprint.pprint("The 'ohnosecond':")
properprint.pprint("The 'ohnosecond' is the fraction of time between making a mistake and realizing it.")
properprint.pprint("(Oh, and please fix the hole you've created)")
end
--[[ Explode
]]--
function boom()
print("|--------------|")
print("| |-| |-| |")
print("| |----| |")
print("| |--------| |")
print("| |--------| |")
print("| |- -| |")
print("|--------------|")
print("....\"Have you exploded today?\"...")
end
-- TAB AUTOCOMLETE HELPER FUNCTIONS --
--[[ Add Text to result array if it fits
@param String option: Autocomplete option to check
@param String texttocomplete: The already typed in text to.. complete...
@param Table result: Array to add the option to if it passes the check
]]--
function addtoresultifitfits(option,texttocomplete,result)
if startsWith(option,texttocomplete) then
result[#result+1] = string.sub(option,#texttocomplete+1)
end
return result
end
-- Functions to complete different subcommands of a command
-- Complete action (eg. "update" or "list")
function completeaction(curText)
result = {}
for i,v in pairs(actions) do
if (not (v["comment"] == nil)) then
result = addtoresultifitfits(i,curText,result)
end
end
return result
end
-- Complete packageid (filter can be nil to display all, "installed" to only recommend installed packages or "not installed" to only recommend not installed packages)
autocompletepackagecache = {}
function completepackageid(curText,filterstate)
result = {}
if curText=="" or curText==nil then
packagedata = readData("/.ccpt/packagedata",false)
if not packagedata then
return {}
end
autocompletepackagecache = packagedata
end
if not (filterstate==nil) then
installedversion = readData("/.ccpt/installedpackages",true)
end
for i,v in pairs(autocompletepackagecache) do
if filterstate=="installed" then
if not (installedversion[i]==nil) then
result = addtoresultifitfits(i,curText,result)
end
elseif filterstate=="not installed" then
if installedversion[i]==nil then
result = addtoresultifitfits(i,curText,result)
end
else
result = addtoresultifitfits(i,curText,result)
end
end
return result
end
-- Complete packageid, but only for custom packages, which is much simpler
function completecustompackageid(curText)
result = {}
custompackages = readData("/.ccpt/custompackages",true)
for i,v in pairs(custompackages) do
result = addtoresultifitfits(i,curText,result)
end
return result
end
--[[ Recursive function to go through the 'autocomplete' array and complete commands accordingly
@param Table lookup: Part of the 'autocomplete' array to look autocomplete up in
@param String lastText: Numeric array of parameters before the current one
@param String curText: The already typed in text to.. complete...
@param int iterator: Last position in the lookup array
@return Table completeoptions: Availible complete options
]]--
function tabcompletehelper(lookup,lastText,curText,iterator)
if lookup[lastText[iterator]]==nil then
return {}
end
if #lastText==iterator then
return lookup[lastText[iterator]]["func"](curText,unpack(lookup[lastText[iterator]]["funcargs"]))
elseif lookup[lastText[iterator]]["next"]==nil then
return {}
else
return tabcompletehelper(lookup[lastText[iterator]]["next"],lastText,curText,iterator+1)
end
end
-- CONFIG ARRAYS --
--[[ Array to store subcommands, help comment and function
]]--
actions = {
update = {
func = update,
comment = "Search for new Versions & Packages"
},
install = {
func = install,
comment = "Install new Packages"
},
upgrade = {
func = upgrade,
comment = "Upgrade installed Packages"
},
uninstall = {
func = uninstall,
comment = "Remove installed Packages"
},
add = {
func = add,
comment = "Add Package URL to local list"
},
remove = {
func = remove,
comment = "Remove Package URL from local list"
},
list = {
func = list,
comment = "List installed and able to install Packages"
},
info = {
func = info,
comment = "Information about a package"
},
startup = {
func = startup
},
help = {
func = help,
comment = "Print help"
},
version = {
func = version,
comment = "Print CCPT Version"
},
zzzzzz = {
func = zzzzzz
},
boom = {
func = boom
}
}
--[[ Array to store different installation methodes and corresponding functions
]]--
installtypes = {
library = {
install = installlibrary,
update = installlibrary,
remove = removelibrary,
desc = "Single file library"
},
script = {
install = installscript,
update = updatescript,
remove = removescript,
desc = "Programm installed via Installer"
}
}
--[[ Array to store autocomplete information
]]--
autocomplete = {
func = completeaction,
funcargs = {},
next = {
install = {
func = completepackageid,
funcargs = {"not installed"}
},
uninstall = {
func = completepackageid,
funcargs = {"installed"}
},
remove = {
func = completecustompackageid,
funcargs = {}
},
info = {
func = completepackageid,
funcargs = {}
}
}
}
-- MAIN AUTOCOMLETE FUNCTION --
function tabcomplete(shell, parNumber, curText, lastText)
result = {}
tabcompletehelper(
{
ccpt = autocomplete
},
lastText,curText or "",1)
return result
end
-- MAIN PROGRAM --
-- Register autocomplete function
shell.setCompletionFunction("ccpt", tabcomplete)
-- Add to startup file to run at startup
startup = readFile("startup","") or ""
if not startsWith(startup,"-- ccpt: Seach for updates\nshell.run(\"ccpt\",\"startup\")") then
startup = "-- ccpt: Seach for updates\nshell.run(\"ccpt\",\"startup\")\n\n" .. startup
storeFile("startup",startup)
print("[Installer] Startup entry created!")
end
-- Call required function
if #args==0 then
properprint.pprint("Incomplete command, missing: 'Action'; Type 'ccpt help' for syntax.")
else if actions[args[1]]==nil then
properprint.pprint("Action '" .. args[1] .. "' is unknown. Type 'ccpt help' for syntax.")
else
actions[args[1]]["func"]()
end
end
-- List stats of recent operation
if not (installed+updated+removed==0) then
if installed==1 then
actionmessage = "1 package installed, "
else
actionmessage = installed .. " packages installed, "
end
if updated==1 then
actionmessage = actionmessage .. "1 package updated, "
else
actionmessage = actionmessage .. updated .. " packages updated, "
end
if removed==1 then
actionmessage = actionmessage .. "1 package removed."
else
actionmessage = actionmessage .. removed .. " packages removed."
end
properprint.pprint(actionmessage)
end