mirror of
https://github.com/kepler155c/opus
synced 2024-12-24 23:50:26 +00:00
custom help files + redo System UI
This commit is contained in:
parent
3de03bef22
commit
26564cbcc1
@ -7,6 +7,7 @@ local Config = { }
|
|||||||
|
|
||||||
function Config.load(fname, data)
|
function Config.load(fname, data)
|
||||||
local filename = 'usr/config/' .. fname
|
local filename = 'usr/config/' .. fname
|
||||||
|
data = data or { }
|
||||||
|
|
||||||
if not fs.exists('usr/config') then
|
if not fs.exists('usr/config') then
|
||||||
fs.makeDir('usr/config')
|
fs.makeDir('usr/config')
|
||||||
|
42
sys/apis/turtle/home.lua
Normal file
42
sys/apis/turtle/home.lua
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
local Config = require('config')
|
||||||
|
local GPS = require('gps')
|
||||||
|
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
|
local Home = { }
|
||||||
|
|
||||||
|
function Home.go()
|
||||||
|
local config = { }
|
||||||
|
Config.load('gps', config)
|
||||||
|
|
||||||
|
if config.home then
|
||||||
|
if turtle.enableGPS() then
|
||||||
|
return turtle.pathfind(config.home)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function Home.set()
|
||||||
|
local config = { }
|
||||||
|
Config.load('gps', config)
|
||||||
|
|
||||||
|
local pt = GPS.getPoint()
|
||||||
|
if pt then
|
||||||
|
local originalHeading = turtle.point.heading
|
||||||
|
local heading = GPS.getHeading()
|
||||||
|
if heading then
|
||||||
|
local turns = (turtle.point.heading - originalHeading) % 4
|
||||||
|
pt.heading = (heading - turns) % 4
|
||||||
|
config.home = pt
|
||||||
|
Config.update('gps', config)
|
||||||
|
|
||||||
|
pt = GPS.getPoint()
|
||||||
|
pt.heading = heading
|
||||||
|
turtle.setPoint(pt, true)
|
||||||
|
turtle._goto(config.home)
|
||||||
|
return config.home
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return Home
|
@ -2250,6 +2250,13 @@ function UI.Tabs:add(children)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function UI.Tabs:selectTab(tab)
|
||||||
|
local menuItem = Util.find(self.tabBar:getFocusables(), 'tabUid', tab.uid)
|
||||||
|
if menuItem then
|
||||||
|
self.tabBar:emit({ type = 'tab_select', button = { uid = menuItem.uid } })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function UI.Tabs:enable()
|
function UI.Tabs:enable()
|
||||||
self.enabled = true
|
self.enabled = true
|
||||||
self.tabBar:enable()
|
self.tabBar:enable()
|
||||||
@ -2999,6 +3006,7 @@ function UI.Chooser:eventHandler(event)
|
|||||||
if event.key == 'right' or event.key == 'space' then
|
if event.key == 'right' or event.key == 'space' then
|
||||||
local _,k = Util.find(self.choices, 'value', self.value)
|
local _,k = Util.find(self.choices, 'value', self.value)
|
||||||
local choice
|
local choice
|
||||||
|
if not k then k = 1 end
|
||||||
if k and k < #self.choices then
|
if k and k < #self.choices then
|
||||||
choice = self.choices[k+1]
|
choice = self.choices[k+1]
|
||||||
else
|
else
|
||||||
@ -3021,7 +3029,7 @@ function UI.Chooser:eventHandler(event)
|
|||||||
self:draw()
|
self:draw()
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
elseif event.type == 'mouse_click' then
|
elseif event.type == 'mouse_click' or event.type == 'mouse_doubleclick' then
|
||||||
if event.x == 1 then
|
if event.x == 1 then
|
||||||
self:emit({ type = 'key', key = 'left' })
|
self:emit({ type = 'key', key = 'left' })
|
||||||
return true
|
return true
|
||||||
|
@ -1,16 +1,9 @@
|
|||||||
_G.requireInjector(_ENV)
|
local Config = require('config')
|
||||||
|
local UI = require('ui')
|
||||||
|
local Util = require('util')
|
||||||
|
|
||||||
local Config = require('config')
|
local fs = _G.fs
|
||||||
local Security = require('security')
|
local shell = _ENV.shell
|
||||||
local SHA1 = require('sha1')
|
|
||||||
local UI = require('ui')
|
|
||||||
local Util = require('util')
|
|
||||||
|
|
||||||
local fs = _G.fs
|
|
||||||
local os = _G.os
|
|
||||||
local settings = _G.settings
|
|
||||||
local shell = _ENV.shell
|
|
||||||
local turtle = _G.turtle
|
|
||||||
|
|
||||||
UI:configure('System', ...)
|
UI:configure('System', ...)
|
||||||
|
|
||||||
@ -23,116 +16,18 @@ Config.load('shell', env)
|
|||||||
|
|
||||||
local systemPage = UI.Page {
|
local systemPage = UI.Page {
|
||||||
tabs = UI.Tabs {
|
tabs = UI.Tabs {
|
||||||
pathTab = UI.Window {
|
settings = UI.Window {
|
||||||
tabTitle = 'Path',
|
tabTitle = 'Category',
|
||||||
entry = UI.TextEntry {
|
|
||||||
x = 2, y = 2, ex = -2,
|
|
||||||
limit = 256,
|
|
||||||
value = shell.path(),
|
|
||||||
shadowText = 'enter system path',
|
|
||||||
accelerators = {
|
|
||||||
enter = 'update_path',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid = UI.Grid {
|
grid = UI.Grid {
|
||||||
y = 4,
|
y = 2,
|
||||||
disableHeader = true,
|
columns = {
|
||||||
columns = { { key = 'value' } },
|
{ heading = 'Name', key = 'name' },
|
||||||
|
{ heading = 'Description', key = 'description' },
|
||||||
|
},
|
||||||
|
sortColumn = 'name',
|
||||||
autospace = true,
|
autospace = true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
aliasTab = UI.Window {
|
|
||||||
tabTitle = 'Alias',
|
|
||||||
alias = UI.TextEntry {
|
|
||||||
x = 2, y = 2, ex = -2,
|
|
||||||
limit = 32,
|
|
||||||
shadowText = 'Alias',
|
|
||||||
},
|
|
||||||
path = UI.TextEntry {
|
|
||||||
y = 3, x = 2, ex = -2,
|
|
||||||
limit = 256,
|
|
||||||
shadowText = 'Program path',
|
|
||||||
accelerators = {
|
|
||||||
enter = 'new_alias',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid = UI.Grid {
|
|
||||||
y = 5,
|
|
||||||
sortColumn = 'alias',
|
|
||||||
columns = {
|
|
||||||
{ heading = 'Alias', key = 'alias' },
|
|
||||||
{ heading = 'Program', key = 'path' },
|
|
||||||
},
|
|
||||||
accelerators = {
|
|
||||||
delete = 'delete_alias',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
passwordTab = UI.Window {
|
|
||||||
tabTitle = 'Password',
|
|
||||||
oldPass = UI.TextEntry {
|
|
||||||
x = 2, y = 2, ex = -2,
|
|
||||||
limit = 32,
|
|
||||||
mask = true,
|
|
||||||
shadowText = 'old password',
|
|
||||||
inactive = not Security.getPassword(),
|
|
||||||
},
|
|
||||||
newPass = UI.TextEntry {
|
|
||||||
y = 3, x = 2, ex = -2,
|
|
||||||
limit = 32,
|
|
||||||
mask = true,
|
|
||||||
shadowText = 'new password',
|
|
||||||
accelerators = {
|
|
||||||
enter = 'new_password',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
button = UI.Button {
|
|
||||||
x = 2, y = 5,
|
|
||||||
text = 'Update',
|
|
||||||
event = 'update_password',
|
|
||||||
},
|
|
||||||
info = UI.TextArea {
|
|
||||||
x = 2, ex = -2,
|
|
||||||
y = 7,
|
|
||||||
inactive = true,
|
|
||||||
value = 'Add a password to enable other computers to connect to this one.',
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
infoTab = UI.Window {
|
|
||||||
tabTitle = 'Info',
|
|
||||||
labelText = UI.Text {
|
|
||||||
x = 3, y = 2,
|
|
||||||
value = 'Label'
|
|
||||||
},
|
|
||||||
label = UI.TextEntry {
|
|
||||||
x = 9, y = 2, ex = -4,
|
|
||||||
limit = 32,
|
|
||||||
value = os.getComputerLabel(),
|
|
||||||
accelerators = {
|
|
||||||
enter = 'update_label',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
grid = UI.ScrollingGrid {
|
|
||||||
y = 3,
|
|
||||||
values = {
|
|
||||||
{ name = '', value = '' },
|
|
||||||
{ name = 'CC version', value = Util.getVersion() },
|
|
||||||
{ name = 'Lua version', value = _VERSION },
|
|
||||||
{ name = 'MC version', value = Util.getMinecraftVersion() },
|
|
||||||
{ name = 'Disk free', value = Util.toBytes(fs.getFreeSpace('/')) },
|
|
||||||
{ name = 'Computer ID', value = tostring(os.getComputerID()) },
|
|
||||||
{ name = 'Day', value = tostring(os.day()) },
|
|
||||||
},
|
|
||||||
inactive = true,
|
|
||||||
columns = {
|
|
||||||
{ key = 'name', width = 12 },
|
|
||||||
{ key = 'value' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
notification = UI.Notification(),
|
notification = UI.Notification(),
|
||||||
accelerators = {
|
accelerators = {
|
||||||
@ -140,177 +35,15 @@ local systemPage = UI.Page {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if turtle then
|
function systemPage.tabs.settings:eventHandler(event)
|
||||||
pcall(function()
|
if event.type == 'grid_select' then
|
||||||
local Home = require('turtle.home')
|
local tab = event.selected.tab
|
||||||
-- TODO: dont rely on turtle.home
|
if not systemPage.tabs[tab.tabTitle] then
|
||||||
local values = { }
|
systemPage.tabs:add({ [ tab.tabTitle ] = tab })
|
||||||
Config.load('gps', values.home and { values.home } or { })
|
tab:disable()
|
||||||
|
|
||||||
systemPage.tabs:add({
|
|
||||||
gpsTab = UI.Window {
|
|
||||||
tabTitle = 'GPS',
|
|
||||||
labelText = UI.Text {
|
|
||||||
x = 3, y = 2,
|
|
||||||
value = 'On restart, return to this location'
|
|
||||||
},
|
|
||||||
grid = UI.Grid {
|
|
||||||
x = 3, ex = -3, y = 4,
|
|
||||||
height = 2,
|
|
||||||
values = values,
|
|
||||||
inactive = true,
|
|
||||||
columns = {
|
|
||||||
{ heading = 'x', key = 'x' },
|
|
||||||
{ heading = 'y', key = 'y' },
|
|
||||||
{ heading = 'z', key = 'z' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
button1 = UI.Button {
|
|
||||||
x = 3, y = 7,
|
|
||||||
text = 'Set home',
|
|
||||||
event = 'gps_set',
|
|
||||||
},
|
|
||||||
button2 = UI.Button {
|
|
||||||
ex = -3, y = 7, width = 7,
|
|
||||||
text = 'Clear',
|
|
||||||
event = 'gps_clear',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
function systemPage.tabs.gpsTab:eventHandler(event)
|
|
||||||
if event.type == 'gps_set' then
|
|
||||||
systemPage.notification:info('Determining location', 10)
|
|
||||||
systemPage:sync()
|
|
||||||
if Home.set() then
|
|
||||||
Config.load('gps', values)
|
|
||||||
self.grid:setValues(values.home and { values.home } or { })
|
|
||||||
self.grid:draw()
|
|
||||||
systemPage.notification:success('Location set')
|
|
||||||
else
|
|
||||||
systemPage.notification:error('Unable to determine location')
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
elseif event.type == 'gps_clear' then
|
|
||||||
fs.delete('usr/config/gps')
|
|
||||||
self.grid:setValues({ })
|
|
||||||
self.grid:draw()
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end)
|
systemPage.tabs:selectTab(tab)
|
||||||
end
|
self.parent:draw()
|
||||||
|
|
||||||
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 = value,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
systemPage.tabs:add({
|
|
||||||
settingsTab = UI.Window {
|
|
||||||
tabTitle = 'Settings',
|
|
||||||
grid = UI.Grid {
|
|
||||||
y = 1,
|
|
||||||
values = values,
|
|
||||||
autospace = true,
|
|
||||||
sortColumn = 'name',
|
|
||||||
columns = {
|
|
||||||
{ heading = 'Setting', key = 'name' },
|
|
||||||
{ heading = 'Value', key = 'value' },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
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()
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function systemPage.tabs.pathTab.grid:draw()
|
|
||||||
self.values = { }
|
|
||||||
for _,v in ipairs(Util.split(env.path, '(.-):')) do
|
|
||||||
table.insert(self.values, { value = v })
|
|
||||||
end
|
|
||||||
self:update()
|
|
||||||
UI.Grid.draw(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
function systemPage.tabs.pathTab:eventHandler(event)
|
|
||||||
if event.type == 'update_path' then
|
|
||||||
env.path = self.entry.value
|
|
||||||
self.grid:setIndex(self.grid:getIndex())
|
|
||||||
self.grid:draw()
|
|
||||||
Config.update('shell', env)
|
|
||||||
systemPage.notification:success('reboot to take effect')
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function systemPage.tabs.aliasTab.grid:draw()
|
|
||||||
self.values = { }
|
|
||||||
for k,v in pairs(env.aliases) do
|
|
||||||
table.insert(self.values, { alias = k, path = v })
|
|
||||||
end
|
|
||||||
self:update()
|
|
||||||
UI.Grid.draw(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
function systemPage.tabs.aliasTab:eventHandler(event)
|
|
||||||
if event.type == 'delete_alias' then
|
|
||||||
env.aliases[self.grid:getSelected().alias] = nil
|
|
||||||
self.grid:setIndex(self.grid:getIndex())
|
|
||||||
self.grid:draw()
|
|
||||||
Config.update('shell', env)
|
|
||||||
systemPage.notification:success('reboot to take effect')
|
|
||||||
return true
|
|
||||||
|
|
||||||
elseif event.type == 'new_alias' then
|
|
||||||
env.aliases[self.alias.value] = self.path.value
|
|
||||||
self.alias:reset()
|
|
||||||
self.path:reset()
|
|
||||||
self:draw()
|
|
||||||
self:setFocus(self.alias)
|
|
||||||
Config.update('shell', env)
|
|
||||||
systemPage.notification:success('reboot to take effect')
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function systemPage.tabs.passwordTab:eventHandler(event)
|
|
||||||
if event.type == 'update_password' then
|
|
||||||
if #self.newPass.value == 0 then
|
|
||||||
systemPage.notification:error('Invalid password')
|
|
||||||
elseif Security.getPassword() and not Security.verifyPassword(SHA1.sha1(self.oldPass.value)) then
|
|
||||||
systemPage.notification:error('Passwords do not match')
|
|
||||||
else
|
|
||||||
Security.updatePassword(SHA1.sha1(self.newPass.value))
|
|
||||||
self.oldPass.inactive = false
|
|
||||||
systemPage.notification:success('Password updated')
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function systemPage.tabs.infoTab:eventHandler(event)
|
|
||||||
if event.type == 'update_label' then
|
|
||||||
os.setComputerLabel(self.label.value)
|
|
||||||
systemPage.notification:success('Label updated')
|
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -318,13 +51,43 @@ end
|
|||||||
function systemPage:eventHandler(event)
|
function systemPage:eventHandler(event)
|
||||||
if event.type == 'quit' then
|
if event.type == 'quit' then
|
||||||
UI:exitPullEvents()
|
UI:exitPullEvents()
|
||||||
|
|
||||||
|
elseif event.type == 'success_message' then
|
||||||
|
self.notification:success(event.message)
|
||||||
|
|
||||||
|
elseif event.type == 'info_message' then
|
||||||
|
self.notification:info(event.message)
|
||||||
|
|
||||||
|
elseif event.type == 'error_message' then
|
||||||
|
self.notification:error(event.message)
|
||||||
|
|
||||||
elseif event.type == 'tab_activate' then
|
elseif event.type == 'tab_activate' then
|
||||||
event.activated:focusFirst()
|
event.activated:focusFirst()
|
||||||
|
|
||||||
else
|
else
|
||||||
return UI.Page.eventHandler(self, event)
|
return UI.Page.eventHandler(self, event)
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function loadDirectory(dir)
|
||||||
|
local plugins = { }
|
||||||
|
for _, file in pairs(fs.list(dir)) do
|
||||||
|
local s, m = Util.run(_ENV, fs.combine(dir, file))
|
||||||
|
if not s and m then
|
||||||
|
_G.printError('Error loading: ' .. file)
|
||||||
|
error(m or 'Unknown error')
|
||||||
|
elseif s and m then
|
||||||
|
table.insert(plugins, { tab = m, name = m.tabTitle, description = m.description })
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return plugins
|
||||||
|
end
|
||||||
|
|
||||||
|
local programDir = fs.getDir(shell.getRunningProgram())
|
||||||
|
local plugins = loadDirectory(fs.combine(programDir, 'system'), { })
|
||||||
|
|
||||||
|
systemPage.tabs.settings.grid:setValues(plugins)
|
||||||
|
|
||||||
UI:setPage(systemPage)
|
UI:setPage(systemPage)
|
||||||
UI:pullEvents()
|
UI:pullEvents()
|
||||||
|
66
sys/apps/system/aliases.lua
Normal file
66
sys/apps/system/aliases.lua
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
local Config = require('config')
|
||||||
|
local UI = require('ui')
|
||||||
|
|
||||||
|
local aliasTab = UI.Window {
|
||||||
|
tabTitle = 'Aliases',
|
||||||
|
description = 'Shell aliases',
|
||||||
|
alias = UI.TextEntry {
|
||||||
|
x = 2, y = 2, ex = -2,
|
||||||
|
limit = 32,
|
||||||
|
shadowText = 'Alias',
|
||||||
|
},
|
||||||
|
path = UI.TextEntry {
|
||||||
|
y = 3, x = 2, ex = -2,
|
||||||
|
limit = 256,
|
||||||
|
shadowText = 'Program path',
|
||||||
|
accelerators = {
|
||||||
|
enter = 'new_alias',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid = UI.Grid {
|
||||||
|
y = 5,
|
||||||
|
sortColumn = 'alias',
|
||||||
|
columns = {
|
||||||
|
{ heading = 'Alias', key = 'alias' },
|
||||||
|
{ heading = 'Program', key = 'path' },
|
||||||
|
},
|
||||||
|
accelerators = {
|
||||||
|
delete = 'delete_alias',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function aliasTab.grid:draw()
|
||||||
|
self.values = { }
|
||||||
|
local env = Config.load('shell')
|
||||||
|
for k,v in pairs(env.aliases) do
|
||||||
|
table.insert(self.values, { alias = k, path = v })
|
||||||
|
end
|
||||||
|
self:update()
|
||||||
|
UI.Grid.draw(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function aliasTab:eventHandler(event)
|
||||||
|
if event.type == 'delete_alias' then
|
||||||
|
local env = Config.load('shell')
|
||||||
|
env.aliases[self.grid:getSelected().alias] = nil
|
||||||
|
self.grid:setIndex(self.grid:getIndex())
|
||||||
|
self.grid:draw()
|
||||||
|
Config.update('shell', env)
|
||||||
|
self:emit({ type = 'success_message', message = 'reboot to take effect' })
|
||||||
|
return true
|
||||||
|
|
||||||
|
elseif event.type == 'new_alias' then
|
||||||
|
local env = Config.load('shell')
|
||||||
|
env.aliases[self.alias.value] = self.path.value
|
||||||
|
self.alias:reset()
|
||||||
|
self.path:reset()
|
||||||
|
self:draw()
|
||||||
|
self:setFocus(self.alias)
|
||||||
|
Config.update('shell', env)
|
||||||
|
self:emit({ type = 'success_message', message = 'reboot to take effect' })
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return aliasTab
|
49
sys/apps/system/label.lua
Normal file
49
sys/apps/system/label.lua
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
local UI = require('ui')
|
||||||
|
local Util = require('util')
|
||||||
|
|
||||||
|
local fs = _G.fs
|
||||||
|
local os = _G.os
|
||||||
|
|
||||||
|
local labelTab = UI.Window {
|
||||||
|
tabTitle = 'Label',
|
||||||
|
description = 'Set the computer label',
|
||||||
|
labelText = UI.Text {
|
||||||
|
x = 3, y = 2,
|
||||||
|
value = 'Label'
|
||||||
|
},
|
||||||
|
label = UI.TextEntry {
|
||||||
|
x = 9, y = 2, ex = -4,
|
||||||
|
limit = 32,
|
||||||
|
value = os.getComputerLabel(),
|
||||||
|
accelerators = {
|
||||||
|
enter = 'update_label',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid = UI.ScrollingGrid {
|
||||||
|
y = 3,
|
||||||
|
values = {
|
||||||
|
{ name = '', value = '' },
|
||||||
|
{ name = 'CC version', value = Util.getVersion() },
|
||||||
|
{ name = 'Lua version', value = _VERSION },
|
||||||
|
{ name = 'MC version', value = Util.getMinecraftVersion() },
|
||||||
|
{ name = 'Disk free', value = Util.toBytes(fs.getFreeSpace('/')) },
|
||||||
|
{ name = 'Computer ID', value = tostring(os.getComputerID()) },
|
||||||
|
{ name = 'Day', value = tostring(os.day()) },
|
||||||
|
},
|
||||||
|
inactive = true,
|
||||||
|
columns = {
|
||||||
|
{ key = 'name', width = 12 },
|
||||||
|
{ key = 'value' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function labelTab:eventHandler(event)
|
||||||
|
if event.type == 'update_label' then
|
||||||
|
os.setComputerLabel(self.label.value)
|
||||||
|
self:emit({ type = 'success_message', message = 'Label updated' })
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return labelTab
|
56
sys/apps/system/network.lua
Normal file
56
sys/apps/system/network.lua
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
local Config = require('config')
|
||||||
|
local UI = require('ui')
|
||||||
|
|
||||||
|
local device = _G.device
|
||||||
|
|
||||||
|
local tab = UI.Window {
|
||||||
|
tabTitle = 'Network',
|
||||||
|
description = 'Networking options',
|
||||||
|
form = UI.Form {
|
||||||
|
x = 2,
|
||||||
|
manualControls = true,
|
||||||
|
modem = UI.Chooser {
|
||||||
|
formLabel = 'Modem', formKey = 'modem',
|
||||||
|
nochoice = 'auto',
|
||||||
|
},
|
||||||
|
update = UI.Button {
|
||||||
|
x = 9, y = 4,
|
||||||
|
text = 'Update', event = 'form_complete',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function tab:enable()
|
||||||
|
local width = 7
|
||||||
|
local choices = {
|
||||||
|
{ name = 'auto', value = 'auto' },
|
||||||
|
{ name = 'disable', value = 'none' },
|
||||||
|
}
|
||||||
|
|
||||||
|
for k,v in pairs(device) do
|
||||||
|
if v.isWireless and v.isWireless() and k ~= 'wireless_modem' then
|
||||||
|
table.insert(choices, { name = k, value = v.name })
|
||||||
|
width = math.max(width, #k)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
self.form.modem.choices = choices
|
||||||
|
self.form.modem.width = width + 4
|
||||||
|
|
||||||
|
local config = Config.load('os')
|
||||||
|
self.form.modem.value = config.wirelessModem or 'auto'
|
||||||
|
|
||||||
|
UI.Window.enable(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function tab:eventHandler(event)
|
||||||
|
if event.type == 'form_complete' then
|
||||||
|
local config = Config.load('os')
|
||||||
|
config.wirelessModem = self.form.modem.value
|
||||||
|
Config.update('os', config)
|
||||||
|
self:emit({ type = 'success_message', message = 'reboot to take effect' })
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return tab
|
53
sys/apps/system/password.lua
Normal file
53
sys/apps/system/password.lua
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
local Security = require('security')
|
||||||
|
local SHA1 = require('sha1')
|
||||||
|
local UI = require('ui')
|
||||||
|
|
||||||
|
local passwordTab = UI.Window {
|
||||||
|
tabTitle = 'Password',
|
||||||
|
description = 'Wireless network password',
|
||||||
|
oldPass = UI.TextEntry {
|
||||||
|
x = 2, y = 2, ex = -2,
|
||||||
|
limit = 32,
|
||||||
|
mask = true,
|
||||||
|
shadowText = 'old password',
|
||||||
|
inactive = not Security.getPassword(),
|
||||||
|
},
|
||||||
|
newPass = UI.TextEntry {
|
||||||
|
y = 3, x = 2, ex = -2,
|
||||||
|
limit = 32,
|
||||||
|
mask = true,
|
||||||
|
shadowText = 'new password',
|
||||||
|
accelerators = {
|
||||||
|
enter = 'new_password',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
button = UI.Button {
|
||||||
|
x = 2, y = 5,
|
||||||
|
text = 'Update',
|
||||||
|
event = 'update_password',
|
||||||
|
},
|
||||||
|
info = UI.TextArea {
|
||||||
|
x = 2, ex = -2,
|
||||||
|
y = 7,
|
||||||
|
inactive = true,
|
||||||
|
value = 'Add a password to enable other computers to connect to this one.',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function passwordTab:eventHandler(event)
|
||||||
|
if event.type == 'update_password' then
|
||||||
|
if #self.newPass.value == 0 then
|
||||||
|
self:emit({ type = 'error_message', message = 'Invalid password' })
|
||||||
|
|
||||||
|
elseif Security.getPassword() and not Security.verifyPassword(SHA1.sha1(self.oldPass.value)) then
|
||||||
|
self:emit({ type = 'error_message', message = 'Passwords do not match' })
|
||||||
|
|
||||||
|
else
|
||||||
|
Security.updatePassword(SHA1.sha1(self.newPass.value))
|
||||||
|
self.oldPass.inactive = false
|
||||||
|
self:emit({ type = 'success_message', message = 'Password updated' })
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return passwordTab
|
50
sys/apps/system/path.lua
Normal file
50
sys/apps/system/path.lua
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
local Config = require('config')
|
||||||
|
local UI = require('ui')
|
||||||
|
local Util = require('util')
|
||||||
|
|
||||||
|
local shell = _ENV.shell
|
||||||
|
|
||||||
|
local pathTab = UI.Window {
|
||||||
|
tabTitle = 'Path',
|
||||||
|
description = 'Set the shell path',
|
||||||
|
tabClose = true,
|
||||||
|
entry = UI.TextEntry {
|
||||||
|
x = 2, y = 2, ex = -2,
|
||||||
|
limit = 256,
|
||||||
|
value = shell.path(),
|
||||||
|
shadowText = 'enter system path',
|
||||||
|
accelerators = {
|
||||||
|
enter = 'update_path',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
grid = UI.Grid {
|
||||||
|
y = 4,
|
||||||
|
disableHeader = true,
|
||||||
|
columns = { { key = 'value' } },
|
||||||
|
autospace = true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function pathTab.grid:draw()
|
||||||
|
self.values = { }
|
||||||
|
local env = Config.load('shell')
|
||||||
|
for _,v in ipairs(Util.split(env.path, '(.-):')) do
|
||||||
|
table.insert(self.values, { value = v })
|
||||||
|
end
|
||||||
|
self:update()
|
||||||
|
UI.Grid.draw(self)
|
||||||
|
end
|
||||||
|
|
||||||
|
function pathTab:eventHandler(event)
|
||||||
|
if event.type == 'update_path' then
|
||||||
|
local env = Config.load('shell')
|
||||||
|
env.path = self.entry.value
|
||||||
|
self.grid:setIndex(self.grid:getIndex())
|
||||||
|
self.grid:draw()
|
||||||
|
Config.update('shell', env)
|
||||||
|
self:emit({ type = 'success_message', message = 'reboot to take effect' })
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return pathTab
|
47
sys/apps/system/settings.lua
Normal file
47
sys/apps/system/settings.lua
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
local UI = require('ui')
|
||||||
|
|
||||||
|
local settings = _G.settings
|
||||||
|
|
||||||
|
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 = value,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
local settingsTab = UI.Window {
|
||||||
|
tabTitle = 'Settings',
|
||||||
|
description = 'Computercraft configurable settings',
|
||||||
|
grid = UI.Grid {
|
||||||
|
y = 1,
|
||||||
|
values = values,
|
||||||
|
autospace = true,
|
||||||
|
sortColumn = 'name',
|
||||||
|
columns = {
|
||||||
|
{ heading = 'Setting', key = 'name' },
|
||||||
|
{ heading = 'Value', key = 'value' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
function 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()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return settingsTab
|
||||||
|
end
|
62
sys/apps/system/turtle.lua
Normal file
62
sys/apps/system/turtle.lua
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
local Config = require('config')
|
||||||
|
local UI = require('ui')
|
||||||
|
|
||||||
|
local fs = _G.fs
|
||||||
|
local turtle = _G.turtle
|
||||||
|
|
||||||
|
if turtle then
|
||||||
|
local Home = require('turtle.home')
|
||||||
|
local values = { }
|
||||||
|
Config.load('gps', values.home and { values.home } or { })
|
||||||
|
|
||||||
|
local gpsTab = UI.Window {
|
||||||
|
tabTitle = 'GPS',
|
||||||
|
labelText = UI.Text {
|
||||||
|
x = 3, y = 2,
|
||||||
|
value = 'On restart, return to this location'
|
||||||
|
},
|
||||||
|
grid = UI.Grid {
|
||||||
|
x = 3, ex = -3, y = 4,
|
||||||
|
height = 2,
|
||||||
|
values = values,
|
||||||
|
inactive = true,
|
||||||
|
columns = {
|
||||||
|
{ heading = 'x', key = 'x' },
|
||||||
|
{ heading = 'y', key = 'y' },
|
||||||
|
{ heading = 'z', key = 'z' },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
button1 = UI.Button {
|
||||||
|
x = 3, y = 7,
|
||||||
|
text = 'Set home',
|
||||||
|
event = 'gps_set',
|
||||||
|
},
|
||||||
|
button2 = UI.Button {
|
||||||
|
ex = -3, y = 7, width = 7,
|
||||||
|
text = 'Clear',
|
||||||
|
event = 'gps_clear',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
function gpsTab:eventHandler(event)
|
||||||
|
if event.type == 'gps_set' then
|
||||||
|
self:emit({ type = 'info_message', message = 'Determining location' })
|
||||||
|
self:sync()
|
||||||
|
if Home.set() then
|
||||||
|
Config.load('gps', values)
|
||||||
|
self.grid:setValues(values.home and { values.home } or { })
|
||||||
|
self.grid:draw()
|
||||||
|
self:emit({ type = 'success_message', message = 'Location set' })
|
||||||
|
else
|
||||||
|
self:emit({ type = 'error_message', message = 'Unable to determine location' })
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
elseif event.type == 'gps_clear' then
|
||||||
|
fs.delete('usr/config/gps')
|
||||||
|
self.grid:setValues({ })
|
||||||
|
self.grid:draw()
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return gpsTab
|
||||||
|
end
|
@ -18,8 +18,12 @@ end
|
|||||||
|
|
||||||
local function setModem(dev)
|
local function setModem(dev)
|
||||||
if not device.wireless_modem and dev.isWireless() then
|
if not device.wireless_modem and dev.isWireless() then
|
||||||
local config = Config.load('os', { })
|
local config = Config.load('os')
|
||||||
if not config.wirelessModem or dev.name == config.wirelessModem then
|
|
||||||
|
if not config.wirelessModem or
|
||||||
|
config.wirelessModem == 'auto' or
|
||||||
|
dev.name == config.wirelessModem then
|
||||||
|
|
||||||
device.wireless_modem = dev
|
device.wireless_modem = dev
|
||||||
os.queueEvent('device_attach', 'wireless_modem')
|
os.queueEvent('device_attach', 'wireless_modem')
|
||||||
return dev
|
return dev
|
||||||
|
@ -3,8 +3,9 @@ _G.requireInjector(_ENV)
|
|||||||
local Packages = require('packages')
|
local Packages = require('packages')
|
||||||
local Util = require('util')
|
local Util = require('util')
|
||||||
|
|
||||||
|
local fs = _G.fs
|
||||||
|
local help = _G.help
|
||||||
local shell = _ENV.shell
|
local shell = _ENV.shell
|
||||||
local fs = _G.fs
|
|
||||||
|
|
||||||
local appPaths = Util.split(shell.path(), '(.-);')
|
local appPaths = Util.split(shell.path(), '(.-);')
|
||||||
local luaPaths = Util.split(_G.LUA_PATH, '(.-);')
|
local luaPaths = Util.split(_G.LUA_PATH, '(.-);')
|
||||||
@ -26,6 +27,9 @@ end
|
|||||||
-- dependency graph
|
-- dependency graph
|
||||||
-- https://github.com/mpeterv/depgraph/blob/master/src/depgraph/init.lua
|
-- https://github.com/mpeterv/depgraph/blob/master/src/depgraph/init.lua
|
||||||
|
|
||||||
|
local helpPaths = Util.split(help.path(), '(.-):')
|
||||||
|
table.insert(helpPaths, '/sys/help')
|
||||||
|
|
||||||
for name in pairs(Packages:installed()) do
|
for name in pairs(Packages:installed()) do
|
||||||
local packageDir = fs.combine('packages', name)
|
local packageDir = fs.combine('packages', name)
|
||||||
if fs.exists(fs.combine(packageDir, '.install')) then
|
if fs.exists(fs.combine(packageDir, '.install')) then
|
||||||
@ -40,7 +44,14 @@ for name in pairs(Packages:installed()) do
|
|||||||
if fs.exists(apiPath) then
|
if fs.exists(apiPath) then
|
||||||
addPath(luaPaths, apiPath)
|
addPath(luaPaths, apiPath)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local helpPath = fs.combine(fs.combine('packages', name), 'help')
|
||||||
|
if fs.exists(helpPath) then
|
||||||
|
table.insert(helpPaths, helpPath)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
help.setPath(table.concat(helpPaths, ':'))
|
||||||
|
|
||||||
shell.setPath(table.concat(appPaths, ':'))
|
shell.setPath(table.concat(appPaths, ':'))
|
||||||
_G.LUA_PATH = table.concat(luaPaths, ';')
|
_G.LUA_PATH = table.concat(luaPaths, ';')
|
||||||
|
30
sys/help/Opus Applications
Normal file
30
sys/help/Opus Applications
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
Opus applications are grouped into packages with a common theme.
|
||||||
|
|
||||||
|
To install a package, use either the System -> Packages program or the package command line program.
|
||||||
|
|
||||||
|
Shell usage:
|
||||||
|
|
||||||
|
> package list
|
||||||
|
> package install <name>
|
||||||
|
> package update <name>
|
||||||
|
> package uninstall <name>
|
||||||
|
|
||||||
|
Package definitions are located in usr/apps/packages. This file can be modified to add custom packages.
|
||||||
|
|
||||||
|
Current stable packages
|
||||||
|
=======================
|
||||||
|
|
||||||
|
* core
|
||||||
|
Programming and miscellaneous applications. Also contains drivers needed for other packages.
|
||||||
|
|
||||||
|
* builder
|
||||||
|
A program for creating structures from schematic files using a turtle (requires core).
|
||||||
|
|
||||||
|
* farms
|
||||||
|
Various programs for farming resources (wood, crops, animals).
|
||||||
|
|
||||||
|
* milo
|
||||||
|
An A/E like storage implementation (requires core).
|
||||||
|
|
||||||
|
* miners
|
||||||
|
Mining programs.
|
7
sys/help/Wireless Networking
Normal file
7
sys/help/Wireless Networking
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
To establish one-way trust between two computers with modems, run the following in a shell prompt:
|
||||||
|
|
||||||
|
On the target computer, run:
|
||||||
|
> password
|
||||||
|
|
||||||
|
On the source computer, run:
|
||||||
|
> trust <target computer ID>
|
Loading…
Reference in New Issue
Block a user