Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- if not (fs.complete or shell.complete or textutils.complete) then
- _G._NBCOMPLETE = true
- --[[ Read function from 1.78 ]]--
- function _G.read( _sReplaceChar, _tHistory, _fnComplete )
- term.setCursorBlink( true )
- local sLine = ""
- local nHistoryPos
- local nPos = 0
- if _sReplaceChar then
- _sReplaceChar = string.sub( _sReplaceChar, 1, 1 )
- end
- local tCompletions
- local nCompletion
- local function recomplete()
- if _fnComplete and nPos == string.len(sLine) then
- tCompletions = _fnComplete( sLine )
- if tCompletions and #tCompletions > 0 then
- nCompletion = 1
- else
- nCompletion = nil
- end
- else
- tCompletions = nil
- nCompletion = nil
- end
- end
- local function uncomplete()
- tCompletions = nil
- nCompletion = nil
- end
- local w = term.getSize()
- local sx = term.getCursorPos()
- local function redraw( _bClear )
- local nScroll = 0
- if sx + nPos >= w then
- nScroll = (sx + nPos) - w
- end
- local cx,cy = term.getCursorPos()
- term.setCursorPos( sx, cy )
- local sReplace = (_bClear and " ") or _sReplaceChar
- if sReplace then
- term.write( string.rep( sReplace, math.max( string.len(sLine) - nScroll, 0 ) ) )
- else
- term.write( string.sub( sLine, nScroll + 1 ) )
- end
- if nCompletion then
- local sCompletion = tCompletions[ nCompletion ]
- local oldText, oldBg
- if not _bClear then
- oldText = term.getTextColor()
- oldBg = term.getBackgroundColor()
- term.setTextColor( colors.white )
- term.setBackgroundColor( colors.gray )
- end
- if sReplace then
- term.write( string.rep( sReplace, string.len( sCompletion ) ) )
- else
- term.write( sCompletion )
- end
- if not _bClear then
- term.setTextColor( oldText )
- term.setBackgroundColor( oldBg )
- end
- end
- term.setCursorPos( sx + nPos - nScroll, cy )
- end
- local function clear()
- redraw( true )
- end
- recomplete()
- redraw()
- local function acceptCompletion()
- if nCompletion then
- -- Clear
- clear()
- -- Find the common prefix of all the other suggestions which start with the same letter as the current one
- local sCompletion = tCompletions[ nCompletion ]
- sLine = sLine .. sCompletion
- nPos = string.len( sLine )
- -- Redraw
- recomplete()
- redraw()
- end
- end
- while true do
- local sEvent, param = os.pullEvent()
- if sEvent == "char" then
- -- Typed key
- clear()
- sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
- nPos = nPos + 1
- recomplete()
- redraw()
- elseif sEvent == "paste" then
- -- Pasted text
- clear()
- sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
- nPos = nPos + string.len( param )
- recomplete()
- redraw()
- elseif sEvent == "key" then
- if param == keys.enter then
- -- Enter
- if nCompletion then
- clear()
- uncomplete()
- redraw()
- end
- break
- elseif param == keys.left then
- -- Left
- if nPos > 0 then
- clear()
- nPos = nPos - 1
- recomplete()
- redraw()
- end
- elseif param == keys.right then
- -- Right
- if nPos < string.len(sLine) then
- -- Move right
- clear()
- nPos = nPos + 1
- recomplete()
- redraw()
- else
- -- Accept autocomplete
- acceptCompletion()
- end
- elseif param == keys.up or param == keys.down then
- -- Up or down
- if nCompletion then
- -- Cycle completions
- clear()
- if param == keys.up then
- nCompletion = nCompletion - 1
- if nCompletion < 1 then
- nCompletion = #tCompletions
- end
- elseif param == keys.down then
- nCompletion = nCompletion + 1
- if nCompletion > #tCompletions then
- nCompletion = 1
- end
- end
- redraw()
- elseif _tHistory then
- -- Cycle history
- clear()
- 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
- uncomplete()
- redraw()
- end
- elseif param == keys.backspace then
- -- Backspace
- if nPos > 0 then
- clear()
- sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
- nPos = nPos - 1
- recomplete()
- redraw()
- end
- elseif param == keys.home then
- -- Home
- if nPos > 0 then
- clear()
- nPos = 0
- recomplete()
- redraw()
- end
- elseif param == keys.delete then
- -- Delete
- if nPos < string.len(sLine) then
- clear()
- sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )
- recomplete()
- redraw()
- end
- elseif param == keys["end"] then
- -- End
- if nPos < string.len(sLine ) then
- clear()
- nPos = string.len(sLine)
- recomplete()
- redraw()
- end
- elseif param == keys.tab then
- -- Tab (accept autocomplete)
- acceptCompletion()
- end
- elseif sEvent == "term_resize" then
- -- Terminal resized
- w = term.getSize()
- redraw()
- end
- end
- local cx, cy = term.getCursorPos()
- term.setCursorBlink( false )
- term.setCursorPos( w + 1, cy )
- print()
- return sLine
- end
- --[[ Fs completion functions from 1.78 ]]--
- local tEmpty = {}
- function fs.complete( sPath, sLocation, bIncludeFiles, bIncludeDirs )
- bIncludeFiles = (bIncludeFiles ~= false)
- bIncludeDirs = (bIncludeDirs ~= false)
- local sDir = sLocation
- local nStart = 1
- local nSlash = string.find( sPath, "[/\\]", nStart )
- if nSlash == 1 then
- sDir = ""
- nStart = 2
- end
- local sName
- while not sName do
- local nSlash = string.find( sPath, "[/\\]", nStart )
- if nSlash then
- local sPart = string.sub( sPath, nStart, nSlash - 1 )
- sDir = fs.combine( sDir, sPart )
- nStart = nSlash + 1
- else
- sName = string.sub( sPath, nStart )
- end
- end
- if fs.isDir( sDir ) then
- local tResults = {}
- if bIncludeDirs and sPath == "" then
- table.insert( tResults, "." )
- end
- if sDir ~= "" then
- if sPath == "" then
- table.insert( tResults, (bIncludeDirs and "..") or "../" )
- elseif sPath == "." then
- table.insert( tResults, (bIncludeDirs and ".") or "./" )
- end
- end
- local tFiles = fs.list( sDir )
- for n=1,#tFiles do
- local sFile = tFiles[n]
- if #sFile >= #sName and string.sub( sFile, 1, #sName ) == sName then
- local bIsDir = fs.isDir( fs.combine( sDir, sFile ) )
- local sResult = string.sub( sFile, #sName + 1 )
- if bIsDir then
- table.insert( tResults, sResult .. "/" )
- if bIncludeDirs and #sResult > 0 then
- table.insert( tResults, sResult )
- end
- else
- if bIncludeFiles and #sResult > 0 then
- table.insert( tResults, sResult )
- end
- end
- end
- end
- return tResults
- end
- return tEmpty
- end
- --[[ Shell completion functions from 1.78 ]]--
- local tAliases = (parentShell and parentShell.aliases()) or {}
- local function tokenise( ... )
- local sLine = table.concat( { ... }, " " )
- local tWords = {}
- local bQuoted = false
- for match in string.gmatch( sLine .. "\"", "(.-)\"" ) do
- if bQuoted then
- table.insert( tWords, match )
- else
- for m in string.gmatch( match, "[^ \t]+" ) do
- table.insert( tWords, m )
- end
- end
- bQuoted = not bQuoted
- end
- return tWords
- end
- local tCompletionInfo = (parentShell and parentShell.getCompletionInfo()) or {}
- local function completeProgram( sLine )
- if #sLine > 0 and string.sub( sLine, 1, 1 ) == "/" then
- -- Add programs from the root
- return fs.complete( sLine, "", true, false )
- else
- local tResults = {}
- local tSeen = {}
- -- Add aliases
- for sAlias, sCommand in pairs( tAliases ) do
- if #sAlias > #sLine and string.sub( sAlias, 1, #sLine ) == sLine then
- local sResult = string.sub( sAlias, #sLine + 1 )
- if not tSeen[ sResult ] then
- table.insert( tResults, sResult )
- tSeen[ sResult ] = true
- end
- end
- end
- -- Add programs from the path
- local tPrograms = shell.programs()
- for n=1,#tPrograms do
- local sProgram = tPrograms[n]
- if #sProgram > #sLine and string.sub( sProgram, 1, #sLine ) == sLine then
- local sResult = string.sub( sProgram, #sLine + 1 )
- if not tSeen[ sResult ] then
- table.insert( tResults, sResult )
- tSeen[ sResult ] = true
- end
- end
- end
- -- Sort and return
- table.sort( tResults )
- return tResults
- end
- end
- local function completeProgramArgument( sProgram, nArgument, sPart, tPreviousParts )
- local tInfo = tCompletionInfo[ sProgram ]
- if tInfo then
- return tInfo.fnComplete( shell, nArgument, sPart, tPreviousParts )
- end
- return nil
- end
- function shell.complete( sLine )
- if #sLine > 0 then
- local tWords = tokenise( sLine )
- local nIndex = #tWords
- if string.sub( sLine, #sLine, #sLine ) == " " then
- nIndex = nIndex + 1
- end
- if nIndex == 1 then
- local sBit = tWords[1] or ""
- local sPath = shell.resolveProgram( sBit )
- if tCompletionInfo[ sPath ] then
- return { " " }
- else
- local tResults = completeProgram( sBit )
- for n=1,#tResults do
- local sResult = tResults[n]
- local sPath = shell.resolveProgram( sBit .. sResult )
- if tCompletionInfo[ sPath ] then
- tResults[n] = sResult .. " "
- end
- end
- return tResults
- end
- elseif nIndex > 1 then
- local sPath = shell.resolveProgram( tWords[1] )
- local sPart = tWords[nIndex] or ""
- local tPreviousParts = tWords
- tPreviousParts[nIndex] = nil
- return completeProgramArgument( sPath , nIndex - 1, sPart, tPreviousParts )
- end
- end
- return nil
- end
- function shell.completeProgram( sProgram )
- return completeProgram( sProgram )
- end
- function shell.setCompletionFunction( sProgram, fnComplete )
- tCompletionInfo[ sProgram ] = {
- fnComplete = fnComplete
- }
- end
- function shell.getCompletionInfo()
- return tCompletionInfo
- end
- --[[ Textutils completion functions form 1.78 ]]--
- local g_tLuaKeywords = {
- [ "and" ] = true,
- [ "break" ] = true,
- [ "do" ] = true,
- [ "else" ] = true,
- [ "elseif" ] = true,
- [ "end" ] = true,
- [ "false" ] = true,
- [ "for" ] = true,
- [ "function" ] = true,
- [ "if" ] = true,
- [ "in" ] = true,
- [ "local" ] = true,
- [ "nil" ] = true,
- [ "not" ] = true,
- [ "or" ] = true,
- [ "repeat" ] = true,
- [ "return" ] = true,
- [ "then" ] = true,
- [ "true" ] = true,
- [ "until" ] = true,
- [ "while" ] = true,
- }
- local tEmpty = {}
- function textutils.complete( sSearchText, tSearchTable )
- local nStart = 1
- local nDot = string.find( sSearchText, ".", nStart, true )
- local tTable = tSearchTable or _ENV
- while nDot do
- local sPart = string.sub( sSearchText, nStart, nDot - 1 )
- local value = tTable[ sPart ]
- if type( value ) == "table" then
- tTable = value
- nStart = nDot + 1
- nDot = string.find( sSearchText, ".", nStart, true )
- else
- return tEmpty
- end
- end
- local sPart = string.sub( sSearchText, nStart, nDot )
- local nPartLength = string.len( sPart )
- local tResults = {}
- local tSeen = {}
- while tTable do
- for k,v in pairs( tTable ) do
- if not tSeen[k] and type(k) == "string" then
- if string.find( k, sPart, 1, true ) == 1 then
- if not g_tLuaKeywords[k] and string.match( k, "^[%a_][%a%d_]*$" ) then
- local sResult = string.sub( k, nPartLength + 1 )
- if type(v) == "function" then
- sResult = sResult .. "("
- elseif type(v) == "table" and next(v) ~= nil then
- sResult = sResult .. "."
- end
- table.insert( tResults, sResult )
- end
- end
- end
- tSeen[k] = true
- end
- local tMetatable = getmetatable( tTable )
- if tMetatable and type( tMetatable.__index ) == "table" then
- tTable = tMetatable.__index
- else
- tTable = nil
- end
- end
- table.sort( tResults )
- return tResults
- end
- end
- if (_G.settings == nil) then
- nbSettings = true
- local tSettings = {}
- _G.settings = {}
- function _G.settings.set( sName, value )
- if type(sName) ~= "string" or
- (type(value) ~= "string" and type(value) ~= "number" and type(value) ~= "boolean" and type(value) ~= "table") then
- error( "Expected string, value", 2 )
- end
- if type(value) == "table" then
- -- Ensure value is serializeable
- value = textutils.unserialize( textutils.serialize(value) )
- end
- tSettings[ sName ] = value
- end
- local copy
- function copy( value )
- if type(v) == "table" then
- local result = {}
- for k,v in pairs(value) do
- result[k] = copy(v)
- end
- return result
- else
- return value
- end
- end
- function _G.settings.get( sName, default )
- if type(sName) ~= "string" then
- error( "Expected string", 2 )
- end
- local result = tSettings[ sName ]
- if result ~= nil then
- return copy(result)
- else
- return default
- end
- end
- function _G.settings.unset( sName )
- if type(sName) ~= "string" then
- error( "Expected string", 2 )
- end
- tSettings[ sName ] = nil
- end
- function _G.clear()
- tSettings = {}
- end
- function _G.settings.getNames()
- local result = {}
- for k,v in pairs( tSettings ) do
- result[ #result + 1 ] = k
- end
- return result
- end
- function _G.settings.load( sPath )
- if type(sPath) ~= "string" then
- error( "Expected string", 2 )
- end
- local file = fs.open( sPath, "r" )
- if file then
- local sText = file.readAll()
- file.close()
- local tFile = textutils.unserialize( sText )
- if type(tFile) == "table" then
- for k,v in pairs(tFile) do
- if type(k) == "string" and
- (type(v) == "string" or type(v) == "number" or type(v) == "boolean" or type(v) == "table") then
- set( k, v )
- end
- end
- end
- end
- end
- function _G.settings.save( sPath )
- if type(sPath) ~= "string" then
- error( "Expected string", 2 )
- end
- local file = fs.open( sPath, "w" )
- file.write( textutils.serialize( tSettings ) )
- file.close()
- end
- else
- print("Settings API is already loaded.")
- print("Likely because you are running CC 1.77+")
- end
- --[[ Load settings ]]--
- print("\nLoading settings")
- if (settings.nbSettings) then
- settings.load("/.settings")
- if (#settings.getNames() == 0) then
- local settingsFile = fs.open("/.settings",'w')
- settingsFile.write(textutils.serialise({["bios.use_multishell"]=true,["shell.autocomplete"]=true,
- ["shell.allow_disk_startup"]=not command,["shell.allow_startup"]=true,["lua.autocomplete"]=true,
- ["list.show_hidden"]=false,["edit.autocomplete"]=true,}))
- settingsFile.close()
- settings.load("/.settings")
- end
- end
- if (settings.get("bios.use_multishell")) then
- mulishell = nil
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement