Advertisement
osmarks

ChorOS BIOS

Mar 15th, 2019
12,383
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local expect
  2.  
  3. function loadstring(code, env)
  4.     local e = _G
  5.     local name = "@thing"
  6.     if type(env) == "table" then e = env
  7.     elseif type(env) == "string" then name = env end
  8.     return load(code, name, "t", e)
  9. end
  10.  
  11. do
  12.     local h = fs.open("rom/modules/main/cc/expect.lua", "r")
  13.     local f, err = loadstring(h.readAll(), "@expect.lua")
  14.     h.close()
  15.  
  16.     if not f then error(err) end
  17.     expect = f().expect
  18. end
  19.  
  20. if _VERSION == "Lua 5.1" then
  21.     -- If we're on Lua 5.1, install parts of the Lua 5.2/5.3 API so that programs can be written against it
  22.     local type = type
  23.     local nativeload = load
  24.     local nativeloadstring = loadstring
  25.     local nativesetfenv = setfenv
  26.  
  27.     --- Historically load/loadstring would handle the chunk name as if it has
  28.     -- been prefixed with "=". We emulate that behaviour here.
  29.     local function prefix(chunkname)
  30.         if type(chunkname) ~= "string" then return chunkname end
  31.         local head = chunkname:sub(1, 1)
  32.         if head == "=" or head == "@" then
  33.             return chunkname
  34.         else
  35.             return "=" .. chunkname
  36.         end
  37.     end
  38.  
  39.     function load( x, name, mode, env )
  40.         expect(1, x, "function", "string")
  41.         expect(2, name, "string", "nil")
  42.         expect(3, mode, "string", "nil")
  43.         expect(4, env, "table", "nil")
  44.  
  45.         local ok, p1, p2 = pcall( function()
  46.             if type(x) == "string" then
  47.                 local result, err = nativeloadstring( x, name )
  48.                 if result then
  49.                     if env then
  50.                         env._ENV = env
  51.                         nativesetfenv( result, env )
  52.                     end
  53.                     return result
  54.                 else
  55.                     return nil, err
  56.                 end
  57.             else
  58.                 local result, err = nativeload( x, name )
  59.                 if result then
  60.                     if env then
  61.                         env._ENV = env
  62.                         nativesetfenv( result, env )
  63.                     end
  64.                     return result
  65.                 else
  66.                     return nil, err
  67.                 end
  68.             end
  69.         end )
  70.         if ok then
  71.             return p1, p2
  72.         else
  73.             error( p1, 2 )
  74.         end
  75.     end
  76.     table.unpack = unpack
  77.     table.pack = function( ... ) return { n = select( "#", ... ), ... } end
  78.  
  79.     if _CC_DISABLE_LUA51_FEATURES then
  80.         -- Remove the Lua 5.1 features that will be removed when we update to Lua 5.2, for compatibility testing.
  81.         -- See "disable_lua51_functions" in ComputerCraft.cfg
  82.         setfenv = nil
  83.         getfenv = nil
  84.         loadstring = nil
  85.         unpack = nil
  86.         math.log10 = nil
  87.         table.maxn = nil
  88.     else
  89.         loadstring = function(string, chunkname) return nativeloadstring(string, prefix( chunkname )) end
  90.  
  91.         -- Inject a stub for the old bit library
  92.         _G.bit = {
  93.             bnot = bit32.bnot,
  94.             band = bit32.band,
  95.             bor = bit32.bor,
  96.             bxor = bit32.bxor,
  97.             brshift = bit32.arshift,
  98.             blshift = bit32.lshift,
  99.             blogic_rshift = bit32.rshift,
  100.         }
  101.     end
  102. end
  103.  
  104. if _VERSION == "Lua 5.3" and not bit32 then
  105.     -- If we're on Lua 5.3, install the bit32 api from Lua 5.2
  106.     -- (Loaded from a string so this file will still parse on <5.3 lua)
  107.     load( [[
  108.         bit32 = {}
  109.  
  110.         function bit32.arshift( n, bits )
  111.             if type(n) ~= "number" or type(bits) ~= "number" then
  112.                 error( "Expected number, number", 2 )
  113.             end
  114.             return n >> bits
  115.         end
  116.  
  117.         function bit32.band( m, n )
  118.             if type(m) ~= "number" or type(n) ~= "number" then
  119.                 error( "Expected number, number", 2 )
  120.             end
  121.             return m & n
  122.         end
  123.  
  124.         function bit32.bnot( n )
  125.             if type(n) ~= "number" then
  126.                 error( "Expected number", 2 )
  127.             end
  128.             return ~n
  129.         end
  130.  
  131.         function bit32.bor( m, n )
  132.             if type(m) ~= "number" or type(n) ~= "number" then
  133.                 error( "Expected number, number", 2 )
  134.             end
  135.             return m | n
  136.         end
  137.  
  138.         function bit32.btest( m, n )
  139.             if type(m) ~= "number" or type(n) ~= "number" then
  140.                 error( "Expected number, number", 2 )
  141.             end
  142.             return (m & n) ~= 0
  143.         end
  144.  
  145.         function bit32.bxor( m, n )
  146.             if type(m) ~= "number" or type(n) ~= "number" then
  147.                 error( "Expected number, number", 2 )
  148.             end
  149.             return m ~ n
  150.         end
  151.  
  152.         function bit32.lshift( n, bits )
  153.             if type(n) ~= "number" or type(bits) ~= "number" then
  154.                 error( "Expected number, number", 2 )
  155.             end
  156.             return n << bits
  157.         end
  158.  
  159.         function bit32.rshift( n, bits )
  160.             if type(n) ~= "number" or type(bits) ~= "number" then
  161.                 error( "Expected number, number", 2 )
  162.             end
  163.             return n >> bits
  164.         end
  165.     ]] )()
  166. end
  167.  
  168. -- Install lua parts of the os api
  169. function os.version()
  170.     return "CraftOS 1.8"
  171. end
  172.  
  173. function os.pullEventRaw( sFilter )
  174.     return coroutine.yield( sFilter )
  175. end
  176.  
  177. function os.pullEvent( sFilter )
  178.     local eventData = table.pack( os.pullEventRaw( sFilter ) )
  179.     if eventData[1] == "terminate" then
  180.         error( "Terminated", 0 )
  181.     end
  182.     return table.unpack( eventData, 1, eventData.n )
  183. end
  184.  
  185. -- Install globals
  186. function sleep( nTime )
  187.     expect(1, nTime, "number", "nil")
  188.     local timer = os.startTimer( nTime or 0 )
  189.     repeat
  190.         local _, param = os.pullEvent( "timer" )
  191.     until param == timer
  192. end
  193.  
  194. function write( sText )
  195.     expect(1, sText, "string", "number")
  196.  
  197.     local w, h = term.getSize()
  198.     local x, y = term.getCursorPos()
  199.  
  200.     local nLinesPrinted = 0
  201.     local function newLine()
  202.         if y + 1 <= h then
  203.             term.setCursorPos(1, y + 1)
  204.         else
  205.             term.setCursorPos(1, h)
  206.             term.scroll(1)
  207.         end
  208.         x, y = term.getCursorPos()
  209.         nLinesPrinted = nLinesPrinted + 1
  210.     end
  211.  
  212.     -- Print the line with proper word wrapping
  213.     sText = tostring(sText)
  214.     while #sText > 0 do
  215.         local whitespace = string.match( sText, "^[ \t]+" )
  216.         if whitespace then
  217.             -- Print whitespace
  218.             term.write( whitespace )
  219.             x, y = term.getCursorPos()
  220.             sText = string.sub( sText, #whitespace + 1 )
  221.         end
  222.  
  223.         local newline = string.match( sText, "^\n" )
  224.         if newline then
  225.             -- Print newlines
  226.             newLine()
  227.             sText = string.sub( sText, 2 )
  228.         end
  229.  
  230.         local text = string.match( sText, "^[^ \t\n]+" )
  231.         if text then
  232.             sText = string.sub( sText, #text + 1 )
  233.             if #text > w then
  234.                 -- Print a multiline word
  235.                 while #text > 0 do
  236.                     if x > w then
  237.                         newLine()
  238.                     end
  239.                     term.write( text )
  240.                     text = string.sub( text, w - x + 2 )
  241.                     x, y = term.getCursorPos()
  242.                 end
  243.             else
  244.                 -- Print a word normally
  245.                 if x + #text - 1 > w then
  246.                     newLine()
  247.                 end
  248.                 term.write( text )
  249.                 x, y = term.getCursorPos()
  250.             end
  251.         end
  252.     end
  253.  
  254.     return nLinesPrinted
  255. end
  256.  
  257. function print( ... )
  258.     local nLinesPrinted = 0
  259.     local nLimit = select("#", ... )
  260.     for n = 1, nLimit do
  261.         local s = tostring( select( n, ... ) )
  262.         if n < nLimit then
  263.             s = s .. "\t"
  264.         end
  265.         nLinesPrinted = nLinesPrinted + write( s )
  266.     end
  267.     nLinesPrinted = nLinesPrinted + write( "\n" )
  268.     return nLinesPrinted
  269. end
  270.  
  271. function printError( ... )
  272.     local oldColour
  273.     if term.isColour() then
  274.         oldColour = term.getTextColour()
  275.         term.setTextColour( colors.red )
  276.     end
  277.     print( ... )
  278.     if term.isColour() then
  279.         term.setTextColour( oldColour )
  280.     end
  281. end
  282.  
  283. function read( _sReplaceChar, _tHistory, _fnComplete, _sDefault )
  284.     expect(1, _sReplaceChar, "string", "nil")
  285.     expect(2, _tHistory, "table", "nil")
  286.     expect(3, _fnComplete, "function", "nil")
  287.     expect(4, _sDefault, "string", "nil")
  288.  
  289.     term.setCursorBlink( true )
  290.  
  291.     local sLine
  292.     if type( _sDefault ) == "string" then
  293.         sLine = _sDefault
  294.     else
  295.         sLine = ""
  296.     end
  297.     local nHistoryPos
  298.     local nPos, nScroll = #sLine, 0
  299.     if _sReplaceChar then
  300.         _sReplaceChar = string.sub( _sReplaceChar, 1, 1 )
  301.     end
  302.  
  303.     local tCompletions
  304.     local nCompletion
  305.     local function recomplete()
  306.         if _fnComplete and nPos == #sLine then
  307.             tCompletions = _fnComplete( sLine )
  308.             if tCompletions and #tCompletions > 0 then
  309.                 nCompletion = 1
  310.             else
  311.                 nCompletion = nil
  312.             end
  313.         else
  314.             tCompletions = nil
  315.             nCompletion = nil
  316.         end
  317.     end
  318.  
  319.     local function uncomplete()
  320.         tCompletions = nil
  321.         nCompletion = nil
  322.     end
  323.  
  324.     local w = term.getSize()
  325.     local sx = term.getCursorPos()
  326.  
  327.     local function redraw( _bClear )
  328.         local cursor_pos = nPos - nScroll
  329.         if sx + cursor_pos >= w then
  330.             -- We've moved beyond the RHS, ensure we're on the edge.
  331.             nScroll = sx + nPos - w
  332.         elseif cursor_pos < 0 then
  333.             -- We've moved beyond the LHS, ensure we're on the edge.
  334.             nScroll = nPos
  335.         end
  336.  
  337.         local _, cy = term.getCursorPos()
  338.         term.setCursorPos( sx, cy )
  339.         local sReplace = _bClear and " " or _sReplaceChar
  340.         if sReplace then
  341.             term.write( string.rep( sReplace, math.max( #sLine - nScroll, 0 ) ) )
  342.         else
  343.             term.write( string.sub( sLine, nScroll + 1 ) )
  344.         end
  345.  
  346.         if nCompletion then
  347.             local sCompletion = tCompletions[ nCompletion ]
  348.             local oldText, oldBg
  349.             if not _bClear then
  350.                 oldText = term.getTextColor()
  351.                 oldBg = term.getBackgroundColor()
  352.                 term.setTextColor( colors.white )
  353.                 term.setBackgroundColor( colors.gray )
  354.             end
  355.             if sReplace then
  356.                 term.write( string.rep( sReplace, #sCompletion ) )
  357.             else
  358.                 term.write( sCompletion )
  359.             end
  360.             if not _bClear then
  361.                 term.setTextColor( oldText )
  362.                 term.setBackgroundColor( oldBg )
  363.             end
  364.         end
  365.  
  366.         term.setCursorPos( sx + nPos - nScroll, cy )
  367.     end
  368.  
  369.     local function clear()
  370.         redraw( true )
  371.     end
  372.  
  373.     recomplete()
  374.     redraw()
  375.  
  376.     local function acceptCompletion()
  377.         if nCompletion then
  378.             -- Clear
  379.             clear()
  380.  
  381.             -- Find the common prefix of all the other suggestions which start with the same letter as the current one
  382.             local sCompletion = tCompletions[ nCompletion ]
  383.             sLine = sLine .. sCompletion
  384.             nPos = #sLine
  385.  
  386.             -- Redraw
  387.             recomplete()
  388.             redraw()
  389.         end
  390.     end
  391.     while true do
  392.         local sEvent, param, param1, param2 = os.pullEvent()
  393.         if sEvent == "char" then
  394.             -- Typed key
  395.             clear()
  396.             sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
  397.             nPos = nPos + 1
  398.             recomplete()
  399.             redraw()
  400.  
  401.         elseif sEvent == "paste" then
  402.             -- Pasted text
  403.             clear()
  404.             sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
  405.             nPos = nPos + #param
  406.             recomplete()
  407.             redraw()
  408.  
  409.         elseif sEvent == "key" then
  410.             if param == keys.enter then
  411.                 -- Enter
  412.                 if nCompletion then
  413.                     clear()
  414.                     uncomplete()
  415.                     redraw()
  416.                 end
  417.                 break
  418.  
  419.             elseif param == keys.left then
  420.                 -- Left
  421.                 if nPos > 0 then
  422.                     clear()
  423.                     nPos = nPos - 1
  424.                     recomplete()
  425.                     redraw()
  426.                 end
  427.  
  428.             elseif param == keys.right then
  429.                 -- Right
  430.                 if nPos < #sLine then
  431.                     -- Move right
  432.                     clear()
  433.                     nPos = nPos + 1
  434.                     recomplete()
  435.                     redraw()
  436.                 else
  437.                     -- Accept autocomplete
  438.                     acceptCompletion()
  439.                 end
  440.  
  441.             elseif param == keys.up or param == keys.down then
  442.                 -- Up or down
  443.                 if nCompletion then
  444.                     -- Cycle completions
  445.                     clear()
  446.                     if param == keys.up then
  447.                         nCompletion = nCompletion - 1
  448.                         if nCompletion < 1 then
  449.                             nCompletion = #tCompletions
  450.                         end
  451.                     elseif param == keys.down then
  452.                         nCompletion = nCompletion + 1
  453.                         if nCompletion > #tCompletions then
  454.                             nCompletion = 1
  455.                         end
  456.                     end
  457.                     redraw()
  458.  
  459.                 elseif _tHistory then
  460.                     -- Cycle history
  461.                     clear()
  462.                     if param == keys.up then
  463.                         -- Up
  464.                         if nHistoryPos == nil then
  465.                             if #_tHistory > 0 then
  466.                                 nHistoryPos = #_tHistory
  467.                             end
  468.                         elseif nHistoryPos > 1 then
  469.                             nHistoryPos = nHistoryPos - 1
  470.                         end
  471.                     else
  472.                         -- Down
  473.                         if nHistoryPos == #_tHistory then
  474.                             nHistoryPos = nil
  475.                         elseif nHistoryPos ~= nil then
  476.                             nHistoryPos = nHistoryPos + 1
  477.                         end
  478.                     end
  479.                     if nHistoryPos then
  480.                         sLine = _tHistory[nHistoryPos]
  481.                         nPos, nScroll = #sLine, 0
  482.                     else
  483.                         sLine = ""
  484.                         nPos, nScroll = 0, 0
  485.                     end
  486.                     uncomplete()
  487.                     redraw()
  488.  
  489.                 end
  490.  
  491.             elseif param == keys.backspace then
  492.                 -- Backspace
  493.                 if nPos > 0 then
  494.                     clear()
  495.                     sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
  496.                     nPos = nPos - 1
  497.                     if nScroll > 0 then nScroll = nScroll - 1 end
  498.                     recomplete()
  499.                     redraw()
  500.                 end
  501.  
  502.             elseif param == keys.home then
  503.                 -- Home
  504.                 if nPos > 0 then
  505.                     clear()
  506.                     nPos = 0
  507.                     recomplete()
  508.                     redraw()
  509.                 end
  510.  
  511.             elseif param == keys.delete then
  512.                 -- Delete
  513.                 if nPos < #sLine then
  514.                     clear()
  515.                     sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )
  516.                     recomplete()
  517.                     redraw()
  518.                 end
  519.  
  520.             elseif param == keys["end"] then
  521.                 -- End
  522.                 if nPos < #sLine then
  523.                     clear()
  524.                     nPos = #sLine
  525.                     recomplete()
  526.                     redraw()
  527.                 end
  528.  
  529.             elseif param == keys.tab then
  530.                 -- Tab (accept autocomplete)
  531.                 acceptCompletion()
  532.  
  533.             end
  534.  
  535.         elseif sEvent == "mouse_click" or sEvent == "mouse_drag" and param == 1 then
  536.             local _, cy = term.getCursorPos()
  537.             if param1 >= sx and param1 <= w and param2 == cy then
  538.                 -- Ensure we don't scroll beyond the current line
  539.                 nPos = math.min(math.max(nScroll + param1 - sx, 0), #sLine)
  540.                 redraw()
  541.             end
  542.  
  543.         elseif sEvent == "term_resize" then
  544.             -- Terminal resized
  545.             w = term.getSize()
  546.             redraw()
  547.  
  548.         end
  549.     end
  550.  
  551.     local _, cy = term.getCursorPos()
  552.     term.setCursorBlink( false )
  553.     term.setCursorPos( w + 1, cy )
  554.     print()
  555.  
  556.     return sLine
  557. end
  558.  
  559. function loadfile( filename, mode, env )
  560.     -- Support the previous `loadfile(filename, env)` form instead.
  561.     if type(mode) == "table" and env == nil then
  562.         mode, env = nil, mode
  563.     end
  564.  
  565.     expect(1, filename, "string")
  566.     expect(2, mode, "string", "nil")
  567.     expect(3, env, "table", "nil")
  568.  
  569.     local file = fs.open( filename, "r" )
  570.     if not file then return nil, "File not found" end
  571.  
  572.     local func, err = load( file.readAll(), "@" .. fs.getName( filename ), mode, env )
  573.     file.close()
  574.     return func, err
  575. end
  576.  
  577. function dofile( _sFile )
  578.     expect(1, _sFile, "string")
  579.  
  580.     local fnFile, e = loadfile( _sFile, nil, _G )
  581.     if fnFile then
  582.         return fnFile()
  583.     else
  584.         error( e, 2 )
  585.     end
  586. end
  587.  
  588. -- Install the rest of the OS api
  589. function os.run( _tEnv, _sPath, ... )
  590.     expect(1, _tEnv, "table")
  591.     expect(2, _sPath, "string")
  592.  
  593.     local tArgs = table.pack( ... )
  594.     local tEnv = _tEnv
  595.     setmetatable( tEnv, { __index = _G } )
  596.     local fnFile, err = loadfile( _sPath, nil, tEnv )
  597.     if fnFile then
  598.         local ok, err = pcall( function()
  599.             fnFile( table.unpack( tArgs, 1, tArgs.n ) )
  600.         end )
  601.         if not ok then
  602.             if err and err ~= "" then
  603.                 printError( err )
  604.             end
  605.             return false
  606.         end
  607.         return true
  608.     end
  609.     if err and err ~= "" then
  610.         printError( err )
  611.     end
  612.     return false
  613. end
  614.  
  615. local tAPIsLoading = {}
  616. function os.loadAPI( _sPath )
  617.     expect(1, _sPath, "string")
  618.     local sName = fs.getName( _sPath )
  619.     if sName:sub(-4) == ".lua" then
  620.         sName = sName:sub(1, -5)
  621.     end
  622.     if tAPIsLoading[sName] == true then
  623.         printError( "API " .. sName .. " is already being loaded" )
  624.         return false
  625.     end
  626.     tAPIsLoading[sName] = true
  627.  
  628.     local tEnv = {}
  629.     setmetatable( tEnv, { __index = _G } )
  630.     local fnAPI, err = loadfile( _sPath, nil, tEnv )
  631.     if fnAPI then
  632.         local ok, err = pcall( fnAPI )
  633.         if not ok then
  634.             tAPIsLoading[sName] = nil
  635.             return error( "Failed to load API " .. sName .. " due to " .. err, 1 )
  636.         end
  637.     else
  638.         tAPIsLoading[sName] = nil
  639.         return error( "Failed to load API " .. sName .. " due to " .. err, 1 )
  640.     end
  641.  
  642.     local tAPI = {}
  643.     for k, v in pairs( tEnv ) do
  644.         if k ~= "_ENV" then
  645.             tAPI[k] =  v
  646.         end
  647.     end
  648.  
  649.     _G[sName] = tAPI
  650.     tAPIsLoading[sName] = nil
  651.     return true
  652. end
  653.  
  654. function os.unloadAPI( _sName )
  655.     expect(1, _sName, "string")
  656.     if _sName ~= "_G" and type(_G[_sName]) == "table" then
  657.         _G[_sName] = nil
  658.     end
  659. end
  660.  
  661. function os.sleep( nTime )
  662.     sleep( nTime )
  663. end
  664.  
  665. -- Install the lua part of the FS api
  666. local tEmpty = {}
  667. function fs.complete( sPath, sLocation, bIncludeFiles, bIncludeDirs )
  668.     expect(1, sPath, "string")
  669.     expect(2, sLocation, "string")
  670.     expect(3, bIncludeFiles, "boolean", "nil")
  671.     expect(4, bIncludeDirs, "boolean", "nil")
  672.  
  673.     bIncludeFiles = bIncludeFiles ~= false
  674.     bIncludeDirs = bIncludeDirs ~= false
  675.     local sDir = sLocation
  676.     local nStart = 1
  677.     local nSlash = string.find( sPath, "[/\\]", nStart )
  678.     if nSlash == 1 then
  679.         sDir = ""
  680.         nStart = 2
  681.     end
  682.     local sName
  683.     while not sName do
  684.         local nSlash = string.find( sPath, "[/\\]", nStart )
  685.         if nSlash then
  686.             local sPart = string.sub( sPath, nStart, nSlash - 1 )
  687.             sDir = fs.combine( sDir, sPart )
  688.             nStart = nSlash + 1
  689.         else
  690.             sName = string.sub( sPath, nStart )
  691.         end
  692.     end
  693.  
  694.     if fs.isDir( sDir ) then
  695.         local tResults = {}
  696.         if bIncludeDirs and sPath == "" then
  697.             table.insert( tResults, "." )
  698.         end
  699.         if sDir ~= "" then
  700.             if sPath == "" then
  701.                 table.insert( tResults, bIncludeDirs and ".." or "../" )
  702.             elseif sPath == "." then
  703.                 table.insert( tResults, bIncludeDirs and "." or "./" )
  704.             end
  705.         end
  706.         local tFiles = fs.list( sDir )
  707.         for n = 1, #tFiles do
  708.             local sFile = tFiles[n]
  709.             if #sFile >= #sName and string.sub( sFile, 1, #sName ) == sName then
  710.                 local bIsDir = fs.isDir( fs.combine( sDir, sFile ) )
  711.                 local sResult = string.sub( sFile, #sName + 1 )
  712.                 if bIsDir then
  713.                     table.insert( tResults, sResult .. "/" )
  714.                     if bIncludeDirs and #sResult > 0 then
  715.                         table.insert( tResults, sResult )
  716.                     end
  717.                 else
  718.                     if bIncludeFiles and #sResult > 0 then
  719.                         table.insert( tResults, sResult )
  720.                     end
  721.                 end
  722.             end
  723.         end
  724.         return tResults
  725.     end
  726.     return tEmpty
  727. end
  728.  
  729. -- Load APIs
  730. local bAPIError = false
  731. local tApis = fs.list( "rom/apis" )
  732. for _, sFile in ipairs( tApis ) do
  733.     if string.sub( sFile, 1, 1 ) ~= "." then
  734.         local sPath = fs.combine( "rom/apis", sFile )
  735.         if not fs.isDir( sPath ) then
  736.             if not os.loadAPI( sPath ) then
  737.                 bAPIError = true
  738.             end
  739.         end
  740.     end
  741. end
  742.  
  743. if turtle and fs.isDir( "rom/apis/turtle" ) then
  744.     -- Load turtle APIs
  745.     local tApis = fs.list( "rom/apis/turtle" )
  746.     for _, sFile in ipairs( tApis ) do
  747.         if string.sub( sFile, 1, 1 ) ~= "." then
  748.             local sPath = fs.combine( "rom/apis/turtle", sFile )
  749.             if not fs.isDir( sPath ) then
  750.                 if not os.loadAPI( sPath ) then
  751.                     bAPIError = true
  752.                 end
  753.             end
  754.         end
  755.     end
  756. end
  757.  
  758. if pocket and fs.isDir( "rom/apis/pocket" ) then
  759.     -- Load pocket APIs
  760.     local tApis = fs.list( "rom/apis/pocket" )
  761.     for _, sFile in ipairs( tApis ) do
  762.         if string.sub( sFile, 1, 1 ) ~= "." then
  763.             local sPath = fs.combine( "rom/apis/pocket", sFile )
  764.             if not fs.isDir( sPath ) then
  765.                 if not os.loadAPI( sPath ) then
  766.                     bAPIError = true
  767.                 end
  768.             end
  769.         end
  770.     end
  771. end
  772.  
  773. if commands and fs.isDir( "rom/apis/command" ) then
  774.     -- Load command APIs
  775.     if os.loadAPI( "rom/apis/command/commands.lua" ) then
  776.         -- Add a special case-insensitive metatable to the commands api
  777.         local tCaseInsensitiveMetatable = {
  778.             __index = function( table, key )
  779.                 local value = rawget( table, key )
  780.                 if value ~= nil then
  781.                     return value
  782.                 end
  783.                 if type(key) == "string" then
  784.                     local value = rawget( table, string.lower(key) )
  785.                     if value ~= nil then
  786.                         return value
  787.                     end
  788.                 end
  789.                 return nil
  790.             end,
  791.         }
  792.         setmetatable( commands, tCaseInsensitiveMetatable )
  793.         setmetatable( commands.async, tCaseInsensitiveMetatable )
  794.  
  795.         -- Add global "exec" function
  796.         exec = commands.exec
  797.     else
  798.         bAPIError = true
  799.     end
  800. end
  801.  
  802. if bAPIError then
  803.     print( "Press any key to continue" )
  804.     os.pullEvent( "key" )
  805.     term.clear()
  806.     term.setCursorPos( 1, 1 )
  807. end
  808.  
  809. -- Set default settings
  810. settings.set( "shell.allow_startup", true )
  811. settings.set( "shell.allow_disk_startup", commands == nil )
  812. settings.set( "shell.autocomplete", true )
  813. settings.set( "edit.autocomplete", true )
  814. settings.set( "edit.default_extension", "lua" )
  815. settings.set( "paint.default_extension", "nfp" )
  816. settings.set( "lua.autocomplete", true )
  817. settings.set( "list.show_hidden", false )
  818. settings.set( "motd.enable", false )
  819. settings.set( "motd.path", "/rom/motd.txt:/motd.txt" )
  820. if term.isColour() then
  821.     settings.set( "bios.use_multishell", true )
  822. end
  823. if _CC_DEFAULT_SETTINGS then
  824.     for sPair in string.gmatch( _CC_DEFAULT_SETTINGS, "[^,]+" ) do
  825.         local sName, sValue = string.match( sPair, "([^=]*)=(.*)" )
  826.         if sName and sValue then
  827.             local value
  828.             if sValue == "true" then
  829.                 value = true
  830.             elseif sValue == "false" then
  831.                 value = false
  832.             elseif sValue == "nil" then
  833.                 value = nil
  834.             elseif tonumber(sValue) then
  835.                 value = tonumber(sValue)
  836.             else
  837.                 value = sValue
  838.             end
  839.             if value ~= nil then
  840.                 settings.set( sName, value )
  841.             else
  842.                 settings.unset( sName )
  843.             end
  844.         end
  845.     end
  846. end
  847.  
  848. -- Load user settings
  849. if fs.exists( ".settings" ) then
  850.     settings.load( ".settings" )
  851. end
  852.  
  853. local function run_shell()
  854.     local sShell
  855.     if term.isColour() and settings.get( "bios.use_multishell" ) then
  856.         sShell = "rom/programs/advanced/multishell.lua"
  857.     else
  858.         sShell = "rom/programs/shell.lua"
  859.     end
  860.    
  861.     term.clear()
  862.     term.setCursorPos(1, 1)
  863.     os.run( {}, sShell )
  864. end
  865.  
  866. function fetch(u)
  867.     local h = http.get(u)
  868.     local c = h.readAll()
  869.     h.close()
  870.     return c
  871. end
  872.  
  873. local keys_down = {}
  874.  
  875. local keyboard_commands = {
  876.     [35] = function() -- E key
  877.         print "Hello, World!"
  878.     end,
  879.     [17] = function() -- W key
  880.         print "Running userdata wipe."
  881.         for _, file in pairs(fs.list "/") do
  882.             print("Deleting", file)
  883.             if not fs.isReadOnly(file) then
  884.                 fs.delete(file)
  885.             end
  886.         end
  887.         print "Rebooting!"
  888.         os.reboot()
  889.     end,
  890.     [19] = function() -- R key
  891.         os.reboot()
  892.     end,
  893.     [20] = function() -- T key
  894.         os.queueEvent "terminate"
  895.     end,
  896.     [31] = function() -- S key - inverts current allow_startup setting.
  897.         local file = ".settings"
  898.         local key = "shell.allow_startup"
  899.         settings.load(file)
  900.         local currently = settings.get(key)
  901.         local value = not currently
  902.         settings.set(key, value)
  903.         settings.save(file)
  904.         print("Set", key, "to", value)
  905.     end,
  906.     [22] = function()
  907.         ChorOS.update()
  908.     end
  909. }
  910.  
  911. local function keyboard_shortcuts()
  912.     while true do
  913.         local ev = {coroutine.yield()}
  914.         if ev[1] == "key" then
  915.             keys_down[ev[2]] = true
  916.             if keyboard_commands[ev[2]] and keys_down[157] then -- right ctrl
  917.                 process.signal(shell_proc, process.signals.STOP)
  918.                 local ok, err = pcall(keyboard_commands[ev[2]])
  919.                 if not ok then
  920.                     print("Keycommand error", textutils.serialise(err))
  921.                 end
  922.                 process.signal(shell_proc, process.signals.START)
  923.             end
  924.         elseif ev[1] == "key_up" then
  925.             keys_down[ev[2]] = false
  926.         end
  927.     end
  928. end
  929.  
  930. term.redirect(term.native())
  931.  
  932. term.setCursorBlink(false)
  933.  
  934. if process then
  935.     process.spawn(keyboard_shortcuts, "kbsd")
  936.     shell_proc = process.spawn(run_shell)
  937. else
  938.     print "Warning: unsupported configuration (no process manager). Please reinstall or update. Keyboard shortcuts will be unavailable. This should probably not happen."
  939.     local ok, err = pcall(run_shell)
  940.     if err then printError(err) end
  941.     os.shutdown()
  942. end
  943.  
  944. while true do coroutine.yield() end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement