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