format and installer branches

This commit is contained in:
kepler155c@gmail.com 2018-01-24 17:39:38 -05:00
parent 1eea0d7cd8
commit 5a32fe208e
80 changed files with 10742 additions and 10156 deletions

View File

@ -93,3 +93,4 @@ if bootOptions[bootOption].args then
else
print(bootOptions[bootOption].prompt)
end

151
sys/apis/entry.lua Normal file
View File

@ -0,0 +1,151 @@
local class = require('class')
local os = _G.os
local Entry = class()
function Entry:init(args)
self.pos = 0
self.scroll = 0
self.value = ''
self.width = args.width
self.limit = 1024
end
function Entry:reset()
self.pos = 0
self.scroll = 0
self.value = ''
end
local function nextWord(line, cx)
local result = { line:find("(%w+)", cx) }
if #result > 1 and result[2] > cx then
return result[2] + 1
elseif #result > 0 and result[1] == cx then
result = { line:find("(%w+)", result[2] + 1) }
if #result > 0 then
return result[1]
end
end
end
function Entry:updateScroll()
if self.pos - self.scroll > self.width then
self.scroll = self.pos - (self.width)
elseif self.pos < self.scroll then
self.scroll = self.pos
end
end
function Entry:process(ie)
local updated = false
if ie.code == 'left' then
if self.pos > 0 then
self.pos = math.max(self.pos - 1, 0)
updated = true
end
elseif ie.code == 'right' then
local input = tostring(self.value)
if self.pos < #input then
self.pos = math.min(self.pos + 1, #input)
updated = true
end
elseif ie.code == 'home' then
if self.pos ~= 0 then
self.pos = 0
updated = true
end
elseif ie.code == 'end' then
if self.pos ~= #tostring(self.value) then
self.pos = #tostring(self.value)
updated = true
end
elseif ie.code == 'backspace' then
if self.pos > 0 then
local input = tostring(self.value)
self.value = input:sub(1, self.pos - 1) .. input:sub(self.pos + 1)
self.pos = self.pos - 1
updated = true
end
elseif ie.code == 'control-right' then
local nx = nextWord(self.value, self.pos + 1)
if nx then
self.pos = math.min(nx - 1, #self.value)
elseif self.pos < #self.value then
self.pos = #self.value
end
updated = true
elseif ie.code == 'control-left' then
if self.pos ~= 0 then
local lx = 1
while true do
local nx = nextWord(self.value, lx)
if not nx or nx >= self.pos then
break
end
lx = nx
end
if not lx then
self.pos = 0
else
self.pos = lx - 1
end
updated = true
end
elseif ie.code == 'delete' then
local input = tostring(self.value)
if self.pos < #input then
self.value = input:sub(1, self.pos) .. input:sub(self.pos + 2)
self.update = true
updated = true
end
elseif ie.code == 'char' then
local input = tostring(self.value)
if #input < self.limit then
self.value = input:sub(1, self.pos) .. ie.ch .. input:sub(self.pos + 1)
self.pos = self.pos + 1
self.update = true
updated = true
end
elseif ie.code == 'copy' then
os.queueEvent('clipboard_copy', self.value)
elseif ie.code == 'paste' then
local input = tostring(self.value)
if #input + #ie.text > self.limit then
ie.text = ie.text:sub(1, self.limit-#input)
end
self.value = input:sub(1, self.pos) .. ie.text .. input:sub(self.pos + 1)
self.pos = self.pos + #ie.text
updated = true
elseif ie.code == 'mouse_click' then
-- need starting x passed in instead of hardcoding 3
self.pos = math.min(ie.x - 3 + self.scroll, #self.value)
updated = true
elseif ie.code == 'mouse_rightclick' then
local input = tostring(self.value)
if #input > 0 then
self:reset()
updated = true
end
end
self:updateScroll()
return updated
end
return Entry

View File

@ -24,15 +24,22 @@ end
function input:toCode(ch, code)
local result = { }
if not ch and code == 1 then
ch = 'escape'
end
if keyboard.state[keys.leftCtrl] or keyboard.state[keys.rightCtrl] or
code == keys.leftCtrl or code == keys.rightCtrl then
table.insert(result, 'control')
end
if keyboard.state[keys.leftAlt] or keyboard.state[keys.rightAlt] or
code == keys.leftAlt or code == keys.rightAlt then
table.insert(result, 'alt')
end
-- the key-up event for alt keys is not generated if the minecraft
-- window loses focus
--
-- if keyboard.state[keys.leftAlt] or keyboard.state[keys.rightAlt] or
-- code == keys.leftAlt or code == keys.rightAlt then
-- table.insert(result, 'alt')
-- end
if keyboard.state[keys.leftShift] or keyboard.state[keys.rightShift] or
code == keys.leftShift or code == keys.rightShift then
@ -65,13 +72,13 @@ function input:translate(event, code, p1, p2)
if p1 then -- key is held down
if not modifiers[code] then
self.fired = true
return input:toCode(keys.getName(code), code)
return { code = input:toCode(keys.getName(code), code) }
end
else
self.state[code] = true
if self:modifierPressed() and not modifiers[code] or code == 57 then
self.fired = true
return input:toCode(keys.getName(code), code)
return { code = input:toCode(keys.getName(code), code) }
else
self.fired = false
end
@ -80,7 +87,7 @@ function input:translate(event, code, p1, p2)
elseif event == 'char' then
if not self:modifierPressed() then
self.fired = true
return input:toCode(code)
return { code = event, ch = input:toCode(code) }
end
elseif event == 'key_up' then
@ -89,16 +96,18 @@ function input:translate(event, code, p1, p2)
self.fired = true
local ch = input:toCode(keys.getName(code), code)
self.state[code] = nil
return ch
return { code = ch }
end
end
self.state[code] = nil
elseif event == 'paste' then
--self.state[keys.leftCtrl] = nil
--self.state[keys.rightCtrl] = nil
self.fired = true
return input:toCode('paste', 255)
if keyboard.state[keys.leftShift] or keyboard.state[keys.rightShift] then
return { code = 'shift-paste', text = code }
else
return { code = 'paste', text = code }
end
elseif event == 'mouse_click' then
local buttons = { 'mouse_click', 'mouse_rightclick' }
@ -108,7 +117,12 @@ function input:translate(event, code, p1, p2)
elseif event == 'mouse_drag' then
self.mfired = true
self.fired = true
return input:toCode('mouse_drag', 255)
return {
code = input:toCode('mouse_drag', 255),
button = code,
x = p1,
y = p2,
}
elseif event == 'mouse_up' then
if not self.mfired then
@ -130,15 +144,27 @@ function input:translate(event, code, p1, p2)
self.mfired = input:toCode(self.mch, 255)
end
self.fired = true
return self.mfired
return {
code = self.mfired,
button = code,
x = p1,
y = p2,
}
elseif event == "mouse_scroll" then
local directions = {
[ -1 ] = 'scrollUp',
[ 1 ] = 'scrollDown'
[ -1 ] = 'scroll_up',
[ 1 ] = 'scroll_down'
}
self.fired = true
return input:toCode(directions[code], 255)
return {
code = input:toCode(directions[code], 255),
x = p1,
y = p2,
}
elseif event == 'terminate' then
return { code = 'terminate' }
end
end
@ -146,7 +172,7 @@ function input:test()
while true do
local ch = self:translate(os.pullEvent())
if ch then
print('GOT: ' .. tostring(ch))
Util.print(ch)
end
end
end

View File

@ -9,23 +9,8 @@
This work is under MIT-LICENSE
Copyright (c) 2012-2013 Roland Yonaba.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
-- https://opensource.org/licenses/MIT
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
--]]
local _VERSION = ""

View File

@ -11,24 +11,7 @@ local sha1 = {
Copyright (c) 2013 Enrique Garcia Cota + Eike Decker + Jeffrey Friedl
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
https://opensource.org/licenses/MIT
]]
}

View File

@ -50,8 +50,9 @@ function Terminal.scrollable(win, maxScroll)
function win.write(text)
local _, h = win.getSize()
text = tostring(text) or ''
scrollTo(#lines - h)
win.blit(tostring(text),
win.blit(text,
_rep(palette[win.getTextColor()], #text),
_rep(palette[win.getBackgroundColor()], #text))
local x, y = win.getCursorPos()

View File

@ -1,5 +1,3 @@
_G.requireInjector()
local Grid = require('jumper.grid')
local Pathfinder = require('jumper.pathfinder')
local Point = require('point')

View File

@ -3,7 +3,6 @@ local class = require('class')
local Event = require('event')
local Input = require('input')
local Peripheral = require('peripheral')
local Terminal = require('terminal')
local Transition = require('ui.transition')
local Util = require('util')
@ -46,12 +45,12 @@ end
local Manager = class()
function Manager:init()
local function keyFunction(event, code, held)
local ch = Input:translate(event, code, held)
local ie = Input:translate(event, code, held)
if ch and self.currentPage then
if ie and self.currentPage then
local target = self.currentPage.focused or self.currentPage
self:inputEvent(target,
{ type = 'key', key = ch, element = target })
{ type = 'key', key = ie.code == 'char' and ie.ch or ie.code, element = target })
self.currentPage:sync()
end
end
@ -94,10 +93,10 @@ function Manager:init()
-- this should be moved to the device !
monitor_touch = function(_, side, x, y)
Input:translate('mouse_click', 1, x, y)
local ch = Input:translate('mouse_up', 1, x, y)
local ie = Input:translate('mouse_up', 1, x, y)
if self.currentPage then
if self.currentPage.parent.device.side == side then
self:click(ch, 1, x, y)
self:click(ie.code, 1, x, y)
end
end
end,
@ -117,27 +116,27 @@ function Manager:init()
end,
mouse_up = function(_, button, x, y)
local ch = Input:translate('mouse_up', button, x, y)
local ie = Input:translate('mouse_up', button, x, y)
if ch == 'control-shift-mouse_click' then -- hack
if ie.code == 'control-shift-mouse_click' then -- hack
local event = self.currentPage:pointToChild(x, y)
_ENV.multishell.openTab({
path = 'sys/apps/Lua.lua',
args = { event.element },
focused = true })
elseif ch and self.currentPage then
elseif ie and self.currentPage then
--if not self.currentPage.parent.device.side then
self:click(ch, button, x, y)
self:click(ie.code, button, x, y)
--end
end
end,
mouse_drag = function(_, button, x, y)
local ch = Input:translate('mouse_drag', button, x, y)
if ch and self.currentPage then
local ie = Input:translate('mouse_drag', button, x, y)
if ie and self.currentPage then
local event = self.currentPage:pointToChild(x, y)
event.type = ch
event.type = ie.code
self:inputEvent(event.element, event)
self.currentPage:sync()
end
@ -2298,7 +2297,7 @@ function UI.Wizard:enable()
child:disable()
end
end
self:emit({ type = 'enable_view', view = Util.find(self.pages, 'index', 1) })
self:emit({ type = 'enable_view', next = Util.find(self.pages, 'index', 1) })
end
function UI.Wizard:nextView()
@ -2327,29 +2326,44 @@ end
function UI.Wizard:eventHandler(event)
if event.type == 'nextView' then
self:nextView()
self:draw()
return true
local currentView = Util.find(self.pages, 'enabled', true)
local nextView = Util.find(self.pages, 'index', currentView.index + 1)
currentView:emit({ type = 'enable_view', next = nextView, current = currentView })
elseif event.type == 'previousView' then
self:prevView()
self:draw()
local currentView = Util.find(self.pages, 'enabled', true)
local nextView = Util.find(self.pages, 'index', currentView.index - 1)
currentView:emit({ type = 'enable_view', prev = nextView, current = currentView })
return true
elseif event.type == 'enable_view' then
if Util.find(self.pages, 'index', event.view.index - 1) then
if event.current then
if event.next then
self:addTransition('slideLeft')
elseif event.prev then
self:addTransition('slideRight')
end
event.current:disable()
end
-- a new current view
local current = event.next or event.prev
current:enable()
if Util.find(self.pages, 'index', current.index - 1) then
self.previousButton:enable()
else
self.previousButton:disable()
end
if Util.find(self.pages, 'index', event.view.index + 1) then
if Util.find(self.pages, 'index', current.index + 1) then
self.nextButton.text = 'Next >'
self.nextButton.event = 'nextView'
else
self.nextButton.text = 'Accept'
self.nextButton.event = 'accept'
end
self:draw()
end
end
@ -2422,8 +2436,9 @@ UI.Embedded.defaults = {
function UI.Embedded:setParent()
UI.Window.setParent(self)
self.win = window.create(UI.term.device, 1, 1, self.width, self.height, false)
Canvas.convertWindow(self.win, UI.term.device, self.x, self.y)
Terminal.scrollable(self.win, 100)
Canvas.scrollingWindow(self.win, self.x, self.y)
self.win.setParent(UI.term.device)
self.win.setMaxScroll(100)
local canvas = self:getCanvas()
self.win.canvas.parent = canvas

View File

@ -128,7 +128,7 @@ function Canvas:write(x, y, text, bg, fg)
end
function Canvas:writeBlit(x, y, text, bg, fg)
if y > 0 and y <= self.height and x <= self.width then
if y > 0 and y <= #self.lines and x <= self.width then
local width = #text
-- fix ffs
@ -367,4 +367,132 @@ function Canvas.convertWindow(win, parent, wx, wy)
win.clear()
end
function Canvas.scrollingWindow(win, wx, wy)
local w, h = win.getSize()
local scrollPos = 0
local maxScroll = h
-- canvas lines are are a sliding window within the local lines table
local lines = { }
local parent
local canvas = Canvas({
x = wx,
y = wy,
width = w,
height = h,
isColor = win.isColor(),
})
win.canvas = canvas
local function scrollTo(p, forceRedraw)
local ms = #lines - canvas.height -- max scroll
p = math.min(math.max(p, 0), ms) -- normalize
if p ~= scrollPos or forceRedraw then
scrollPos = p
for i = 1, canvas.height do
canvas.lines[i] = lines[i + scrollPos]
end
canvas:dirty()
end
end
function win.blit(text, fg, bg)
local x, y = win.getCursorPos()
win.canvas:writeBlit(x, y, text, bg, fg)
win.redraw()
end
function win.clear()
lines = { }
for i = 1, canvas.height do
lines[i] = canvas.lines[i]
end
scrollPos = 0
canvas:clear(win.getBackgroundColor(), win.getTextColor())
win.redraw()
end
function win.clearLine()
local _, y = win.getCursorPos()
scrollTo(#lines - canvas.height)
win.canvas:write(1,
y,
_rep(' ', win.canvas.width),
win.getBackgroundColor(),
win.getTextColor())
win.redraw()
end
function win.redraw()
if parent and canvas.visible then
local x, y = win.getCursorPos()
for i = 1, canvas.height do
local line = canvas.lines[i]
if line and line.dirty then
parent.setCursorPos(canvas.x, canvas.y + i - 1)
parent.blit(line.text, line.fg, line.bg)
line.dirty = false
end
end
win.setCursorPos(x, y)
end
end
-- doesn't support negative scrolling...
function win.scroll(n)
for _ = 1, n do
lines[#lines + 1] = {
text = _rep(' ', canvas.width),
fg = _rep(canvas.palette[win.getTextColor()], canvas.width),
bg = _rep(canvas.palette[win.getBackgroundColor()], canvas.width),
}
end
while #lines > maxScroll do
table.remove(lines, 1)
end
scrollTo(maxScroll, true)
win.redraw()
end
function win.scrollDown()
scrollTo(scrollPos + 1)
win.redraw()
end
function win.scrollUp()
scrollTo(scrollPos - 1)
win.redraw()
end
function win.setMaxScroll(ms)
maxScroll = ms
end
function win.setParent(p)
parent = p
end
function win.write(str)
str = tostring(str) or ''
local x, y = win.getCursorPos()
scrollTo(#lines - canvas.height)
win.blit(str,
_rep(canvas.palette[win.getTextColor()], #str),
_rep(canvas.palette[win.getBackgroundColor()], #str))
win.setCursorPos(x + #str, y)
end
function win.reposition(x, y, width, height)
win.canvas.x, win.canvas.y = x, y
win.canvas:resize(width or win.canvas.width, height or win.canvas.height)
end
win.clear()
end
return Canvas

View File

@ -1,4 +1,3 @@
-------------------------------------------------------------------------------
--
-- tek.lib.region
-- Written by Timm S. Mueller <tmueller at schulze-mueller.de>
@ -9,49 +8,11 @@
-- * Franciska Schulze <fschulze at schulze-mueller.de>
-- * Tobias Schwinger <tschwinger at isonews2.com>
--
-- Permission is hereby granted, free of charge, to any person obtaining
-- a copy of this software and associated documentation files (the
-- "Software"), to deal in the Software without restriction, including
-- without limitation the rights to use, copy, modify, merge, publish,
-- distribute, sublicense, and/or sell copies of the Software, and to
-- permit persons to whom the Software is furnished to do so, subject to
-- the following conditions:
-- https://opensource.org/licenses/MIT
--
-- The above copyright notice and this permission notice shall be
-- included in all copies or substantial portions of the Software.
--
-- === Disclaimer ===
--
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--
-- OVERVIEW::
-- This library implements the management of regions, which are
-- collections of non-overlapping rectangles.
--
-- FUNCTIONS::
-- - Region:andRect() - ''And''s a rectangle to a region
-- - Region:andRegion() - ''And''s a region to a region
-- - Region:checkIntersect() - Checks if a rectangle intersects a region
-- - Region:forEach() - Calls a function for each rectangle in a region
-- - Region:get() - Get region's min/max extents
-- - Region.intersect() - Returns the intersection of two rectangles
-- - Region:isEmpty() - Checks if a Region is empty
-- - Region.new() - Creates a new Region
-- - Region:orRect() - ''Or''s a rectangle to a region
-- - Region:orRegion() - ''Or''s a region to a region
-- - Region:setRect() - Resets a region to the given rectangle
-- - Region:shift() - Displaces a region
-- - Region:subRect() - Subtracts a rectangle from a region
-- - Region:subRegion() - Subtracts a region from a region
-- - Region:xorRect() - ''Exclusive Or''s a rectangle to a region
--
-------------------------------------------------------------------------------
-- Some comments have been removed to reduce file size, see:
-- https://github.com/technosaurus/tekui/blob/master/etc/region.lua
-- for the full source
local insert = table.insert
local ipairs = ipairs
@ -65,24 +26,18 @@ Region._VERSION = "Region 11.3"
Region.__index = Region
-------------------------------------------------------------------------------
-- x0, y0, x1, y1 = Region.intersect(d1, d2, d3, d4, s1, s2, s3, s4):
-- Returns the coordinates of a rectangle where a rectangle specified by
-- the coordinates s1, s2, s3, s4 overlaps with the rectangle specified
-- by the coordinates d1, d2, d3, d4. The return value is '''nil''' if
-- the rectangles do not overlap.
-------------------------------------------------------------------------------
function Region.intersect(d1, d2, d3, d4, s1, s2, s3, s4)
if s3 >= d1 and s1 <= d3 and s4 >= d2 and s2 <= d4 then
return max(s1, d1), max(s2, d2), min(s3, d3), min(s4, d4)
end
end
-------------------------------------------------------------------------------
-- insertrect: insert rect to table, merging with an existing one if possible
-------------------------------------------------------------------------------
local function insertrect(d, s1, s2, s3, s4)
for i = 1, min(4, #d) do
local a = d[i]
@ -108,10 +63,7 @@ local function insertrect(d, s1, s2, s3, s4)
insert(d, 1, { s1, s2, s3, s4 })
end
-------------------------------------------------------------------------------
-- cutrect: cut rect d into table of new rects, using rect s as a punch
-------------------------------------------------------------------------------
local function cutrect(d1, d2, d3, d4, s1, s2, s3, s4)
if not Region.intersect(d1, d2, d3, d4, s1, s2, s3, s4) then
return { { d1, d2, d3, d4 } }
@ -135,10 +87,7 @@ local function cutrect(d1, d2, d3, d4, s1, s2, s3, s4)
return r
end
-------------------------------------------------------------------------------
-- cutregion: cut region d, using s as a punch
-------------------------------------------------------------------------------
local function cutregion(d, s1, s2, s3, s4)
local r = { }
for _, dr in ipairs(d) do
@ -150,11 +99,8 @@ local function cutregion(d, s1, s2, s3, s4)
return r
end
-------------------------------------------------------------------------------
-- region = Region.new(r1, r2, r3, r4): Creates a new region from the given
-- coordinates.
-------------------------------------------------------------------------------
function Region.new(r1, r2, r3, r4)
if r1 then
return setmetatable({ region = { { r1, r2, r3, r4 } } }, Region)
@ -162,39 +108,27 @@ function Region.new(r1, r2, r3, r4)
return setmetatable({ region = { } }, Region)
end
-------------------------------------------------------------------------------
-- self = region:setRect(r1, r2, r3, r4): Resets an existing region
-- to the specified rectangle.
-------------------------------------------------------------------------------
function Region:setRect(r1, r2, r3, r4)
self.region = { { r1, r2, r3, r4 } }
return self
end
-------------------------------------------------------------------------------
-- region:orRect(r1, r2, r3, r4): Logical ''or''s a rectangle to a region
-------------------------------------------------------------------------------
function Region:orRect(s1, s2, s3, s4)
self.region = cutregion(self.region, s1, s2, s3, s4)
insertrect(self.region, s1, s2, s3, s4)
end
-------------------------------------------------------------------------------
-- region:orRegion(region): Logical ''or''s another region to a region
-------------------------------------------------------------------------------
function Region:orRegion(s)
for _, r in ipairs(s) do
self:orRect(r[1], r[2], r[3], r[4])
end
end
-------------------------------------------------------------------------------
-- region:andRect(r1, r2, r3, r4): Logical ''and''s a rectange to a region
-------------------------------------------------------------------------------
function Region:andRect(s1, s2, s3, s4)
local r = { }
for _, d in ipairs(self.region) do
@ -207,10 +141,7 @@ function Region:andRect(s1, s2, s3, s4)
self.region = r
end
-------------------------------------------------------------------------------
-- region:xorRect(r1, r2, r3, r4): Logical ''xor''s a rectange to a region
-------------------------------------------------------------------------------
function Region:xorRect(s1, s2, s3, s4)
local r1 = { }
local r2 = { { s1, s2, s3, s4 } }
@ -225,10 +156,7 @@ function Region:xorRect(s1, s2, s3, s4)
self:orRegion(r2)
end
-------------------------------------------------------------------------------
-- self = region:subRect(r1, r2, r3, r4): Subtracts a rectangle from a region
-------------------------------------------------------------------------------
function Region:subRect(s1, s2, s3, s4)
local r1 = { }
for _, d in ipairs(self.region) do
@ -241,10 +169,7 @@ function Region:subRect(s1, s2, s3, s4)
return self
end
-------------------------------------------------------------------------------
-- region:getRect - gets an iterator on the rectangles in a region [internal]
-------------------------------------------------------------------------------
function Region:getRects()
local index = 0
return function(object)
@ -255,12 +180,9 @@ function Region:getRects()
end, self.region
end
-------------------------------------------------------------------------------
-- success = region:checkIntersect(x0, y0, x1, y1): Returns a boolean
-- indicating whether a rectangle specified by its coordinates overlaps
-- with a region.
-------------------------------------------------------------------------------
function Region:checkIntersect(s1, s2, s3, s4)
for _, d in ipairs(self.region) do
if Region.intersect(d[1], d[2], d[3], d[4], s1, s2, s3, s4) then
@ -270,10 +192,7 @@ function Region:checkIntersect(s1, s2, s3, s4)
return false
end
-------------------------------------------------------------------------------
-- region:subRegion(region2): Subtracts {{region2}} from {{region}}.
-------------------------------------------------------------------------------
function Region:subRegion(region)
if region then
for r1, r2, r3, r4 in region:getRects() do
@ -282,10 +201,7 @@ function Region:subRegion(region)
end
end
-------------------------------------------------------------------------------
-- region:andRegion(r): Logically ''and''s a region to a region
-------------------------------------------------------------------------------
function Region:andRegion(s)
local r = { }
for _, s in ipairs(s.region) do
@ -301,23 +217,17 @@ function Region:andRegion(s)
self.region = r
end
-------------------------------------------------------------------------------
-- region:forEach(func, obj, ...): For each rectangle in a region, calls the
-- specified function according the following scheme:
-- func(obj, x0, y0, x1, y1, ...)
-- Extra arguments are passed through to the function.
-------------------------------------------------------------------------------
function Region:forEach(func, obj, ...)
for x0, y0, x1, y1 in self:getRects() do
func(obj, x0, y0, x1, y1, ...)
end
end
-------------------------------------------------------------------------------
-- region:shift(dx, dy): Shifts a region by delta x and y.
-------------------------------------------------------------------------------
function Region:shift(dx, dy)
for _, r in ipairs(self.region) do
r[1] = r[1] + dx
@ -327,18 +237,12 @@ function Region:shift(dx, dy)
end
end
-------------------------------------------------------------------------------
-- region:isEmpty(): Returns '''true''' if a region is empty.
-------------------------------------------------------------------------------
function Region:isEmpty()
return #self.region == 0
end
-------------------------------------------------------------------------------
-- minx, miny, maxx, maxy = region:get(): Get region's min/max extents
-------------------------------------------------------------------------------
function Region:get()
if #self.region > 0 then
local minx = 1000000 -- ui.HUGE

View File

@ -7,24 +7,7 @@ local tween = {
Copyright (c) 2014 Enrique García Cota, Yuichi Tateno, Emmanuel Oga
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Licence details: https://opensource.org/licenses/MIT
]]
}

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local UI = require('ui')
local Util = require('util')

456
sys/apps/Installer.lua Normal file
View File

@ -0,0 +1,456 @@
local colors = _G.colors
local fs = _G.fs
local http = _G.http
local install = _ENV.install
local os = _G.os
local requireInjector
if not install.testing then
local url ='https://raw.githubusercontent.com/kepler155c/opus/master/sys/apis/injector.lua'
requireInjector = load(http.get(url).readAll())()
else
requireInjector = _G.requireInjector
end
requireInjector(_ENV)
if not install.testing then
if package then
for _ = 1, 4 do
table.remove(package.loaders, 1)
end
end
end
local Git = require('git')
local UI = require('ui')
local Util = require('util')
local currentFile = ''
local currentProgress = 0
local cancelEvent
local args = { ... }
local steps = install.steps[args[1] or 'install']
if not steps then
error('Invalid install type')
end
local mode = steps[#steps]
if UI.term.width < 32 then
cancelEvent = 'quit'
end
local page = UI.Page {
backgroundColor = colors.cyan,
titleBar = UI.TitleBar {
event = cancelEvent,
},
wizard = UI.Wizard {
y = 2, ey = -2,
},
notification = UI.Notification(),
accelerators = {
q = 'quit',
},
}
local pages = {
splash = UI.Viewport { },
review = UI.Viewport { },
license = UI.Viewport {
backgroundColor = colors.black,
},
branch = UI.Window {
grid = UI.ScrollingGrid {
ey = -3,
columns = {
{ heading = 'Branch', key = 'branch' },
{ heading = 'Description', key = 'description' },
},
values = install.branches,
autospace = true,
},
},
files = UI.Window {
grid = UI.ScrollingGrid {
ey = -3,
columns = {
{ heading = 'Files', key = 'file' },
},
sortColumn = 'file',
},
},
install = UI.Window {
progressBar = UI.ProgressBar {
y = -1,
},
},
uninstall = UI.Window {
progressBar = UI.ProgressBar {
y = -1,
},
},
}
local function getFileList()
if install.gitRepo then
local gitFiles = Git.list(string.format('%s/%s', install.gitRepo, install.gitBranch or 'master'))
install.files = { }
install.diskspace = 0
for path, entry in pairs(gitFiles) do
install.files[path] = entry.url
install.diskspace = install.diskspace + entry.size
end
end
if not install.files or Util.empty(install.files) then
error('File list is missing or empty')
end
end
--[[ Splash ]]--
function pages.splash:enable()
page.titleBar.title = 'Installer v1.0'
UI.Viewport.enable(self)
end
function pages.splash:draw()
self:clear()
self:setCursorPos(1, 1)
self:print(
string.format('%s v%s\n', install.title, install.version), nil, colors.yellow)
self:print(
string.format('By: %s\n\n%s\n', install.author, install.description))
self.ymax = self.cursorY
end
--[[ License ]]--
function pages.license:enable()
page.titleBar.title = 'License Review'
page.wizard.nextButton.text = 'Accept'
UI.Viewport.enable(self)
end
function pages.license:draw()
self:clear()
self:setCursorPos(1, 1)
self:print(
string.format('Copyright (c) %s %s\n\n', install.copyrightYear,
install.copyrightHolders),
nil, colors.yellow)
self:print(install.license)
self.ymax = self.cursorY + 1
end
--[[ Review ]]--
function pages.review:enable()
if mode == 'uninstall' then
page.nextButton.text = 'Remove'
page.titleBar.title = 'Remove Installed Files'
else
page.wizard.nextButton.text = 'Begin'
page.titleBar.title = 'Download and Install'
end
UI.Viewport.enable(self)
end
function pages.review:draw()
self:clear()
self:setCursorPos(1, 1)
local text = 'Ready to begin installation.\n\nProceeding will download and install the files to the hard drive.'
if mode == 'uninstall' then
text = 'Ready to begin.\n\nProceeding will remove the files previously installed.'
end
self:print(text)
self.ymax = self.cursorY + 1
end
--[[ Files ]]--
function pages.files:enable()
page.titleBar.title = 'Review Files'
self.grid.values = { }
for k,v in pairs(install.files) do
table.insert(self.grid.values, { file = k, code = v })
end
self.grid:update()
UI.Window.enable(self)
end
function pages.files:draw()
self:clear()
local function formatSize(size)
if size >= 1000000 then
return string.format('%dM', math.floor(size/1000000, 2))
elseif size >= 1000 then
return string.format('%dK', math.floor(size/1000, 2))
end
return size
end
if install.diskspace then
local bg = self.backgroundColor
local diskFree = fs.getFreeSpace('/')
if install.diskspace > diskFree then
bg = colors.red
end
local text = string.format('Space Required: %s, Free: %s',
formatSize(install.diskspace), formatSize(diskFree))
if #text > self.width then
text = string.format('Space: %s Free: %s',
formatSize(install.diskspace), formatSize(diskFree))
end
self:write(1, self.height, Util.widthify(text, self.width), bg)
end
self.grid:draw()
end
--[[
function pages.files:view(url)
local s, m = pcall(function()
page.notification:info('Downloading')
page:sync()
Util.download(url, '/.source')
end)
page.notification:disable()
if s then
shell.run('edit /.source')
fs.delete('/.source')
page:draw()
page.notification:cancel()
else
page.notification:error(m:gsub('.*: (.*)', '%1'))
end
end
function pages.files:eventHandler(event)
if event.type == 'grid_select' then
self:view(event.selected.code)
return true
end
end
--]]
local function drawCommon(self)
if currentFile then
self:write(1, 3, 'File:')
self:write(1, 4, Util.widthify(currentFile, self.width))
else
self:write(1, 3, 'Finished')
end
if self.failed then
self:write(1, 5, Util.widthify(self.failed, self.width), colors.red)
end
self:write(1, self.height - 1, 'Progress')
self.progressBar.value = currentProgress
self.progressBar:draw()
self:sync()
end
--[[ Branch ]]--
function pages.branch:enable()
page.titleBar.title = 'Select Branch'
UI.Window.enable(self)
end
function pages.branch:eventHandler(event)
-- user is navigating to next view (not previous)
if event.type == 'enable_view' and event.next then
install.gitBranch = self.grid:getSelected().branch
getFileList()
end
end
--[[ Install ]]--
function pages.install:enable()
page.wizard.cancelButton:disable()
page.wizard.previousButton:disable()
page.wizard.nextButton:disable()
page.titleBar.title = 'Installing...'
page.titleBar.event = nil
UI.Window.enable(self)
page:draw()
page:sync()
local i = 0
local numFiles = Util.size(install.files)
for filename,url in pairs(install.files) do
currentFile = filename
currentProgress = i / numFiles * 100
self:draw(self)
self:sync()
local s, m = pcall(function()
Util.download(url, fs.combine(install.directory or '', filename))
end)
if not s then
self.failed = m:gsub('.*: (.*)', '%1')
break
end
i = i + 1
end
if not self.failed then
currentProgress = 100
currentFile = nil
if install.postInstall then
local s, m = pcall(function() install.postInstall(page, UI) end)
if not s then
self.failed = m:gsub('.*: (.*)', '%1')
end
end
end
page.wizard.nextButton.text = 'Exit'
page.wizard.nextButton.event = 'quit'
if not self.failed and install.rebootAfter then
page.wizard.nextButton.text = 'Reboot'
page.wizard.nextButton.event = 'reboot'
end
page.wizard.nextButton:enable()
page:draw()
page:sync()
if not self.failed and Util.key(args, 'automatic') then
if install.rebootAfter then
os.reboot()
else
UI:exitPullEvents()
end
end
end
function pages.install:draw()
self:clear()
local text = 'The files are being installed'
if #text > self.width then
text = 'Installing files'
end
self:write(1, 1, text, nil, colors.yellow)
drawCommon(self)
end
--[[ Uninstall ]]--
function pages.uninstall:enable()
page.wizard.cancelButton:disable()
page.wizard.previousButton:disable()
page.wizard.nextButton:disable()
page.titleBar.title = 'Uninstalling...'
page.titleBar.event = nil
page:draw()
page:sync()
UI.Window.enable(self)
local function pruneDir(dir)
if #dir > 0 then
if fs.exists(dir) then
local files = fs.list(dir)
if #files == 0 then
fs.delete(dir)
pruneDir(fs.getDir(dir))
end
end
end
end
local i = 0
local numFiles = Util.size(install.files)
for k in pairs(install.files) do
currentFile = k
currentProgress = i / numFiles * 100
self:draw()
self:sync()
fs.delete(k)
pruneDir(fs.getDir(k))
i = i + 1
end
currentProgress = 100
currentFile = nil
page.wizard.nextButton.text = 'Exit'
page.wizard.nextButton.event = 'quit'
page.wizard.nextButton:enable()
page:draw()
page:sync()
end
function pages.uninstall:draw()
self:clear()
self:write(1, 1, 'Uninstalling files', nil, colors.yellow)
drawCommon(self)
end
function page:eventHandler(event)
if event.type == 'cancel' then
UI:exitPullEvents()
elseif event.type == 'reboot' then
os.reboot()
elseif event.type == 'quit' then
UI:exitPullEvents()
else
return UI.Page.eventHandler(self, event)
end
return true
end
function page:enable()
UI.Page.enable(self)
self:setFocus(page.wizard.nextButton)
if UI.term.width < 32 then
page.wizard.cancelButton:disable()
page.wizard.previousButton.x = 2
end
end
getFileList()
local wizardPages = { }
for k,v in ipairs(steps) do
if not pages[v] then
error('Invalid step: ' .. v)
end
wizardPages[k] = pages[v]
wizardPages[k].index = k
wizardPages[k].x = 2
wizardPages[k].y = 2
wizardPages[k].ey = -3
wizardPages[k].ex = -2
end
page.wizard:add(wizardPages)
if Util.key(steps, 'install') and install.preInstall then
install.preInstall(page, UI)
end
UI:setPage(page)
local s, m = pcall(function() UI:pullEvents() end)
if not s then
UI.term:reset()
_G.printError(m)
end

View File

@ -1,6 +1,5 @@
_G.requireInjector(_ENV)
local Event = require('event')
local History = require('history')
local UI = require('ui')
local Util = require('util')
@ -10,8 +9,10 @@ local os = _G.os
local textutils = _G.textutils
local term = _G.term
local _exit
local sandboxEnv = setmetatable(Util.shallowCopy(_ENV), { __index = _G })
sandboxEnv.exit = function() Event.exitPullEvents() end
sandboxEnv.exit = function() _exit = true end
sandboxEnv._echo = function( ... ) return { ... } end
_G.requireInjector(sandboxEnv)
@ -19,7 +20,6 @@ UI:configure('Lua', ...)
local command = ''
local history = History.load('usr/.lua_history', 25)
local extChars = Util.getVersion() > 1.76
local page = UI.Page {
menuBar = UI.MenuBar {
@ -41,10 +41,6 @@ local page = UI.Page {
[ 'control-space' ] = 'autocomplete',
},
},
indicator = UI.Text {
backgroundColor = colors.black,
y = 2, x = -1, width = 1,
},
grid = UI.ScrollingGrid {
y = 3, ey = -2,
columns = {
@ -62,21 +58,10 @@ local page = UI.Page {
},
output = UI.Embedded {
y = -6,
backgroundColor = colors.gray,
},
--notification = UI.Notification(),
}
function page.indicator:showResult(s)
local values = {
[ true ] = { c = colors.green, i = (extChars and '\003') or '+' },
[ false ] = { c = colors.red, i = 'x' }
}
self.textColor = values[s].c
self.value = values[s].i
self:draw()
end
function page:setPrompt(value, focus)
self.prompt:setValue(value)
self.prompt.scroll = 0
@ -133,12 +118,12 @@ end
function page:eventHandler(event)
if event.type == 'global' then
self:setPrompt('', true)
self:setPrompt('_G', true)
self:executeStatement('_G')
command = nil
elseif event.type == 'local' then
self:setPrompt('', true)
self:setPrompt('_ENV', true)
self:executeStatement('_ENV')
command = nil
@ -341,8 +326,11 @@ end
function page:executeStatement(statement)
command = statement
local s, m
local oterm = term.redirect(self.output.win)
local s, m = self:rawExecute(command)
pcall(function()
s, m = self:rawExecute(command)
end)
if not s then
_G.printError(m)
end
@ -353,14 +341,14 @@ function page:executeStatement(statement)
else
self.grid:setValues({ })
self.grid:draw()
if m then
if not self.output.enabled then
if m and not self.output.enabled then
self:emit({ type = 'show_output' })
end
--self.notification:error(m, 5)
end
if _exit then
UI:exitPullEvents()
end
self.indicator:showResult(not not s)
end
local args = { ... }
@ -371,5 +359,4 @@ if args[1] then
end
UI:setPage(page)
Event.pullEvents()
UI.term:reset()
UI:pullEvents()

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local class = require('class')
local Config = require('config')

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local Config = require('config')
local Security = require('security')
@ -201,9 +201,13 @@ end
if settings then
local values = { }
for _,v in pairs(settings.getNames()) do
local value = settings.get(v)
if not value then
value = false
end
table.insert(values, {
name = v,
value = not not settings.get(v),
value = value,
})
end
@ -224,7 +228,9 @@ if settings then
})
function systemPage.tabs.settingsTab:eventHandler(event)
if event.type == 'grid_select' then
if not event.selected.value or type(event.selected.value) == 'boolean' then
event.selected.value = not event.selected.value
end
settings.set(event.selected.name, event.selected.value)
settings.save('.settings')
self.grid:draw()

View File

@ -58,11 +58,7 @@ function page.grid:getDisplayValues(row)
else
row.timestamp = string.format("%sm", math.floor(elapsed/6)/10)
end
if row.isDead then
row.status = 'error'
else
row.status = coroutine.status(row.co)
end
row.status = row.isDead and 'error' or coroutine.status(row.co)
return row
end

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local Event = require('event')
local Util = require('util')

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local Security = require('security')
local SHA1 = require('sha1')

View File

@ -11,7 +11,7 @@ for k,v in pairs(_ENV) do
end
sandboxEnv.shell = shell
_G.requireInjector()
_G.requireInjector(_ENV)
local Util = require('util')
@ -118,6 +118,10 @@ function shell.resolveProgram( _sCommand )
_sCommand = tAliases[_sCommand]
end
if _sCommand:match("^(https?:)") then
return _sCommand
end
local path = shell.resolve(_sCommand)
if fs.exists(path) and not fs.isDir(path) then
return path
@ -325,10 +329,8 @@ function shell.openTab( ... )
local sPath = shell.resolveProgram(sCommand)
if sPath == "sys/apps/shell" then
return _ENV.multishell.launch(Util.shallowCopy(sandboxEnv), sPath, table.unpack(tWords, 2))
elseif sPath ~= nil then
return _ENV.multishell.launch(Util.shallowCopy(sandboxEnv), "sys/apps/shell", sCommand, table.unpack(tWords, 2))
else
return false, "No such program"
return _ENV.multishell.launch(Util.shallowCopy(sandboxEnv), "sys/apps/shell", sCommand, table.unpack(tWords, 2))
end
end
end
@ -352,11 +354,12 @@ if #tArgs > 0 then
end
local Config = require('config')
local Entry = require('entry')
local History = require('history')
local Input = require('input')
local Terminal = require('terminal')
local colors = _G.colors
local keys = _G.keys
local os = _G.os
local term = _G.term
local textutils = _G.textutils
@ -538,128 +541,81 @@ local function autocomplete(line)
end
local function shellRead(history)
term.setCursorBlink( true )
local sLine = ""
local nPos = 0
local w = term.getSize()
local sx = term.getCursorPos()
local lastLen = 0
local entry = Entry({
width = term.getSize() - 3
})
history:reset()
term.setCursorBlink(true)
local function redraw( sReplace )
local nScroll = 0
if sx + nPos >= w then
nScroll = (sx + nPos) - w
end
local function redraw()
local _,cy = term.getCursorPos()
term.setCursorPos( sx, cy )
if sReplace then
term.write( string.rep( sReplace, math.max( string.len(sLine) - nScroll, 0 ) ) )
else
term.write( string.sub( sLine, nScroll + 1 ) )
end
term.setCursorPos( sx + nPos - nScroll, cy )
term.setCursorPos(3, cy)
local filler = #entry.value < lastLen
and string.rep(' ', lastLen - #entry.value)
or ''
local str = string.sub(entry.value, entry.scroll + 1)
term.write(string.sub(str, 1, entry.width) .. filler)
term.setCursorPos(3 + entry.pos - entry.scroll, cy)
lastLen = #entry.value
end
while true do
local sEvent, param = os.pullEventRaw()
local event, p1, p2, p3 = os.pullEventRaw()
if sEvent == "char" then
sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
nPos = nPos + 1
redraw()
elseif sEvent == "paste" then
sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
nPos = nPos + string.len( param )
redraw()
elseif sEvent == 'mouse_click' and param == 2 then
redraw(string.rep(' ', #sLine))
sLine = ''
nPos = 0
redraw()
elseif sEvent == 'mouse_scroll' then
if param == -1 then
local ie = Input:translate(event, p1, p2, p3)
if ie then
if ie.code == 'scroll_up' then
terminal.scrollUp()
else
elseif ie.code == 'scroll_down' then
terminal.scrollDown()
end
elseif sEvent == 'terminate' then
elseif ie.code == 'terminate' then
bExit = true
break
elseif sEvent == "key" then
if param == keys.enter then
-- Enter
elseif ie.code == 'enter' then
break
elseif param == keys.tab then
if nPos == #sLine then
local cline = autocomplete(sLine)
elseif ie.code == 'up' or ie.code == 'down' then
if ie.code == 'up' then
entry.value = history:back() or ''
else
entry.value = history:forward() or ''
end
entry.pos = string.len(entry.value)
entry.scroll = 0
entry:updateScroll()
redraw()
elseif ie.code == 'tab' then
if entry.pos == #entry.value then
local cline = autocomplete(entry.value)
if cline then
sLine = cline
nPos = #sLine
redraw()
end
end
elseif param == keys.left then
if nPos > 0 then
nPos = nPos - 1
redraw()
end
elseif param == keys.right then
if nPos < string.len(sLine) then
redraw(" ")
nPos = nPos + 1
redraw()
end
elseif param == keys.up or param == keys.down then
redraw(" ")
if param == keys.up then
sLine = history:back()
else
sLine = history:forward()
end
if sLine then
nPos = string.len(sLine)
else
sLine = ""
nPos = 0
end
redraw()
elseif param == keys.backspace then
if nPos > 0 then
redraw(" ")
sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
nPos = nPos - 1
redraw()
end
elseif param == keys.home then
redraw(" ")
nPos = 0
redraw()
elseif param == keys.delete then
if nPos < string.len(sLine) then
redraw(" ")
sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )
redraw()
end
elseif param == keys["end"] then
redraw(" ")
nPos = string.len(sLine)
redraw()
end
elseif sEvent == "term_resize" then
w = term.getSize()
entry.value = cline
entry.pos = #entry.value
entry:updateScroll()
redraw()
end
end
local _, cy = term.getCursorPos()
term.setCursorPos( w + 1, cy )
elseif entry:process(ie) then
redraw()
end
elseif event == "term_resize" then
entry.width = term.getSize() - 3
redraw()
end
end
--local _, cy = term.getCursorPos()
--term.setCursorPos( w + 1, cy )
print()
term.setCursorBlink( false )
return sLine
return entry.value
end
local history = History.load('usr/.shell_history', 25)

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local Event = require('event')
local Socket = require('socket')

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local Crypto = require('crypto')
local Security = require('security')

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local Event = require('event')
local Socket = require('socket')

View File

@ -13,13 +13,13 @@ kernel.hook('clipboard_copy', function(_, args)
data = args[1]
end)
keyboard.addHotkey('control-shift-paste', function(_, args)
keyboard.addHotkey('shift-paste', function()
if type(data) == 'table' then
local s, m = pcall(textutils.serialize, data)
data = (s and m) or Util.tostring(data)
end
-- replace the event paste data with our internal data
args[1] = Util.tostring(data or '')
-- args[1] = Util.tostring(data or '')
if data then
os.queueEvent('paste', data)
end

View File

@ -4,7 +4,7 @@ local turtle = _G.turtle
if turtle and modem then
local s, m = turtle.run(function()
_G.requireInjector()
_G.requireInjector(_ENV)
local Config = require('config')
local config = {

View File

@ -1,14 +1,19 @@
if _G.device.wireless_modem then
_G.requireInjector()
_G.requireInjector(_ENV)
local Config = require('config')
local kernel = _G.kernel
local config = { }
Config.load('gps', config)
if config.host and type(config.host) == 'table' then
_ENV._APP_TITLE = 'GPS Daemon'
os.run(_ENV, '/rom/programs/gps', 'host', config.host.x, config.host.y, config.host.z)
print('GPS daemon stopped')
kernel.run({
title = 'GPS Daemon',
hidden = true,
path = '/rom/programs/gps',
args = { 'host', config.host.x, config.host.y, config.host.z },
})
end
end

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local Util = require('util')
@ -10,7 +10,7 @@ local multishell = _ENV.multishell
keyboard.addHotkey('control-o', function()
for _,tab in pairs(multishell.getTabs()) do
if tab.isOverview then
multishell.setFocus(tab.tabId)
multishell.setFocus(tab.uid)
end
end
end)

View File

@ -10,20 +10,17 @@ local multishell = _ENV.multishell
local os = _G.os
local term = _G.term
local routine = kernel.getCurrent()
if multishell then
multishell.setTitle(multishell.getCurrent(), 'System Log')
multishell.hideTab(routine.uid)
end
local function systemLog()
local routine = kernel.getCurrent()
local w, h = kernel.window.getSize()
kernel.window.reposition(1, 2, w, h - 1)
local w, h = kernel.window.getSize()
kernel.window.reposition(1, 2, w, h - 1)
routine.terminal = kernel.window
routine.window = kernel.window
term.redirect(kernel.window)
routine.terminal = kernel.window
routine.window = kernel.window
term.redirect(kernel.window)
kernel.hook('mouse_scroll', function(_, eventData)
kernel.hook('mouse_scroll', function(_, eventData)
local dir, y = eventData[1], eventData[3]
if y > 1 then
@ -36,16 +33,23 @@ kernel.hook('mouse_scroll', function(_, eventData)
end
end
end
end)
end)
keyboard.addHotkey('control-d', function()
keyboard.addHotkey('control-d', function()
local current = kernel.getFocused()
if current.uid ~= routine.uid then
kernel.raise(routine.uid)
elseif kernel.routines[2] then
kernel.raise(kernel.routines[2].uid)
end
end)
end)
os.pullEventRaw('terminate')
keyboard.removeHotkey('control-d')
os.pullEventRaw('terminate')
keyboard.removeHotkey('control-d')
end
multishell.openTab({
title = 'System Log',
fn = systemLog,
hidden = true,
})

View File

@ -1,3 +0,0 @@
term.clear()
term.setCursorPos(1, 1)
print(os.version())

View File

@ -70,8 +70,8 @@ kernel.hook({ 'key', 'key_up', 'char', 'paste' }, function(event, eventData)
-- and fire hotkeys
local hotkey = Input:translate(event, eventData[1], eventData[2])
if hotkey and keyboard.hotkeys[hotkey] then
keyboard.hotkeys[hotkey](event, eventData)
if hotkey and keyboard.hotkeys[hotkey.code] then
keyboard.hotkeys[hotkey.code](event, eventData)
end
end)

View File

@ -2,7 +2,7 @@ if fs.native then
return
end
_G.requireInjector()
_G.requireInjector(_ENV)
local Util = require('util')
local fs = _G.fs

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local Util = require('util')

View File

@ -2,7 +2,7 @@ if not _G.turtle then
return
end
_G.requireInjector()
_G.requireInjector(_ENV)
local Pathing = require('turtle.pathfind')
local GPS = require('gps')

View File

@ -1,4 +1,4 @@
_G.requireInjector()
_G.requireInjector(_ENV)
local Config = require('config')
local Util = require('util')
@ -199,6 +199,10 @@ kernel.hook('multishell_terminate', function(_, eventData)
return true
end)
kernel.hook('terminate', function()
return kernel.getFocused().isOverview
end)
kernel.hook('multishell_redraw', function()
tabsDirty = false