initial commit
This commit is contained in:
commit
646add28a2
17
.luarc.json
Normal file
17
.luarc.json
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/sumneko/vscode-lua/master/setting/schema.json",
|
||||
"Lua.diagnostics.disable": [
|
||||
"undefined-field"
|
||||
],
|
||||
"Lua.diagnostics.globals": [
|
||||
"peripheral",
|
||||
"rednet",
|
||||
"fs",
|
||||
"textutils",
|
||||
"term",
|
||||
"colors",
|
||||
"paintutils",
|
||||
"keys"
|
||||
],
|
||||
"Lua.runtime.version": "Lua 5.1"
|
||||
}
|
3
README.md
Normal file
3
README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Wireless todo list
|
||||
|
||||
Setup a server on which you can store a todo list and access it from a pocket computer.
|
158
client.lua
Normal file
158
client.lua
Normal file
@ -0,0 +1,158 @@
|
||||
local PROTOCOL = "wireless-todo"
|
||||
|
||||
local function pprint(...)
|
||||
local pretty = require("cc.pretty")
|
||||
pretty.pretty_print(...)
|
||||
end
|
||||
|
||||
local function isWirelessModem(peripheral_name)
|
||||
return peripheral.getType(peripheral_name) == "modem"
|
||||
and peripheral.call(peripheral_name, "isWireless")
|
||||
end
|
||||
|
||||
local function getWirelessModem()
|
||||
for _, name in ipairs(peripheral.getNames()) do
|
||||
if isWirelessModem(name) then
|
||||
return name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function splitTextByWidth(text, max_width)
|
||||
local lines = {}
|
||||
local current_line = ""
|
||||
for whitespace, word in text:gmatch("(%s*)([^%s]+)") do
|
||||
if #current_line + #whitespace + #word > max_width then
|
||||
table.insert(lines, current_line)
|
||||
current_line = word
|
||||
else
|
||||
current_line = current_line..whitespace..word
|
||||
end
|
||||
end
|
||||
if #current_line > 0 then
|
||||
table.insert(lines, current_line)
|
||||
end
|
||||
return lines
|
||||
end
|
||||
|
||||
local function drawTodo(todo)
|
||||
local w, h = term.getSize()
|
||||
local x, y = term.getCursorPos()
|
||||
local lines = splitTextByWidth(todo.text, w-4)
|
||||
paintutils.drawFilledBox(x, y, w, y+#lines-1)
|
||||
term.setCursorPos(x, y)
|
||||
|
||||
term.write("[ ] ")
|
||||
if todo.marked then
|
||||
x, y = term.getCursorPos()
|
||||
term.setCursorPos(x-3, y)
|
||||
term.setTextColor(colors.green)
|
||||
term.write("x")
|
||||
term.setTextColor(colors.white)
|
||||
term.setCursorPos(x, y)
|
||||
end
|
||||
|
||||
x, y = term.getCursorPos()
|
||||
for i, line in ipairs(lines) do
|
||||
term.setCursorPos(x, y+i-1)
|
||||
term.write(line)
|
||||
end
|
||||
term.setCursorPos(1, y+#lines)
|
||||
end
|
||||
|
||||
local function drawTodos(todos, selected_todo)
|
||||
local w, h = term.getSize()
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
term.setTextColor(colors.orange)
|
||||
print("===== Wireless Todo ======")
|
||||
|
||||
term.setTextColor(colors.white)
|
||||
for i, todo in ipairs(todos) do
|
||||
if i == selected_todo then
|
||||
term.setBackgroundColor(colors.gray)
|
||||
drawTodo(todo)
|
||||
term.setBackgroundColor(colors.black)
|
||||
else
|
||||
drawTodo(todo)
|
||||
end
|
||||
|
||||
local _, y = term.getCursorPos()
|
||||
end
|
||||
end
|
||||
|
||||
local function getTodoUnderMouse(todos, x, y)
|
||||
local w, h = term.getSize()
|
||||
|
||||
local todo_y = 2
|
||||
for i, todo in ipairs(todos) do
|
||||
local todo_height = #splitTextByWidth(todo.text, w-4)
|
||||
if todo_y <= y and y < todo_y+todo_height then
|
||||
return i
|
||||
end
|
||||
todo_y = todo_y + todo_height
|
||||
end
|
||||
end
|
||||
|
||||
local function main()
|
||||
local modem_name = getWirelessModem()
|
||||
if not modem_name then
|
||||
print("ERROR: please attach a wireless modem")
|
||||
return
|
||||
end
|
||||
|
||||
rednet.open(modem_name)
|
||||
term.clear()
|
||||
term.setCursorPos(1, 1)
|
||||
print("Starting...")
|
||||
|
||||
local servers = {rednet.lookup(PROTOCOL)}
|
||||
local server = servers[1]
|
||||
|
||||
local selected_todo = 1
|
||||
local todos = {
|
||||
{
|
||||
text = "Foo bar baz",
|
||||
marked = false,
|
||||
},
|
||||
{
|
||||
text = "Nobis doloremque explicabo qui amet nihil perspiciatis. ",
|
||||
marked = false,
|
||||
},
|
||||
{ text = "Biz baz", marked = false },
|
||||
{ text = "Biz baz", marked = true },
|
||||
{
|
||||
text = "Nobis doloremque explicabo qui amet nihil perspiciatis. foao ado ao",
|
||||
marked = false,
|
||||
}
|
||||
}
|
||||
rednet.send(server, "get", PROTOCOL)
|
||||
while true do
|
||||
local event = {os.pullEvent()}
|
||||
if event[1] == "rednet_message" and event[4] == PROTOCOL then
|
||||
-- todos = textutils.unserialise(event[3])
|
||||
elseif event[1] == "mouse_up" then
|
||||
local todo_index = getTodoUnderMouse(todos, event[3], event[4])
|
||||
if todo_index then
|
||||
selected_todo = todo_index
|
||||
end
|
||||
elseif event[1] == "key_up" then
|
||||
local key = event[2]
|
||||
if key == keys.up then
|
||||
selected_todo = math.max(selected_todo-1, 1)
|
||||
elseif key == keys.down then
|
||||
selected_todo = math.min(selected_todo+1, #todos)
|
||||
elseif key == keys.space then
|
||||
todos[selected_todo].marked = not todos[selected_todo].marked
|
||||
end
|
||||
end
|
||||
|
||||
drawTodos(todos, selected_todo)
|
||||
end
|
||||
|
||||
-- local _, response = rednet.receive(PROTOCOL)
|
||||
-- pprint(textutils.unserialise(response))
|
||||
end
|
||||
|
||||
-- pprint(splitTextByWidth("foo bar baz", 10))
|
||||
main()
|
137
server.lua
Normal file
137
server.lua
Normal file
@ -0,0 +1,137 @@
|
||||
local PROTOCOL = "wireless-todo"
|
||||
local TODOS_FILE = "todos.data.lua"
|
||||
|
||||
local function pprint(...)
|
||||
local pretty = require("cc.pretty")
|
||||
pretty.pretty_print(...)
|
||||
end
|
||||
|
||||
local function isWirelessModem(peripheral_name)
|
||||
return peripheral.getType(peripheral_name) == "modem"
|
||||
and peripheral.call(peripheral_name, "isWireless")
|
||||
end
|
||||
|
||||
local function getWirelessModem()
|
||||
for _, name in ipairs(peripheral.getNames()) do
|
||||
if isWirelessModem(name) then
|
||||
return name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function readTodos(filename)
|
||||
if fs.exists(filename) then
|
||||
return loadfile(filename)()
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
|
||||
local function writeTodos(filename, todos)
|
||||
local f = fs.open(filename, "w")
|
||||
f.write("return ")
|
||||
f.write(textutils.serialise(todos))
|
||||
f.close()
|
||||
end
|
||||
|
||||
local function includeValue(set, value)
|
||||
for _, v in ipairs(set) do
|
||||
if v == value then
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(set, value)
|
||||
end
|
||||
|
||||
local function decodeMessage(message)
|
||||
local parts = {}
|
||||
for part in message:gmatch("([^\n]+)") do
|
||||
table.insert(parts, part)
|
||||
end
|
||||
return parts
|
||||
end
|
||||
|
||||
local function sendToMultiple(recipients, payload, protocol, except_recepient)
|
||||
for _, recipient in ipairs(recipients) do
|
||||
if recipient ~= except_recepient then
|
||||
rednet.send(recipient, payload, protocol)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function main(hostname)
|
||||
if not hostname then
|
||||
print("ERROR: please provide a hostname")
|
||||
return
|
||||
end
|
||||
|
||||
local modem_name = getWirelessModem()
|
||||
if not modem_name then
|
||||
print("ERROR: please attach a wireless modem")
|
||||
return
|
||||
end
|
||||
|
||||
rednet.open(modem_name)
|
||||
rednet.host(PROTOCOL, hostname)
|
||||
|
||||
local seen_users = {}
|
||||
local todos = readTodos(TODOS_FILE)
|
||||
|
||||
local function updateUsersTodos(except_user)
|
||||
writeTodos(TODOS_FILE, todos)
|
||||
local payload = textutils.serialise(todos, { compact = true })
|
||||
sendToMultiple(seen_users, payload, PROTOCOL, except_user)
|
||||
end
|
||||
|
||||
while true do
|
||||
local sender, message = rednet.receive(PROTOCOL)
|
||||
print(sender, message)
|
||||
local parts = decodeMessage(message)
|
||||
pprint(parts)
|
||||
if parts[1] == "get" then
|
||||
includeValue(seen_users, sender)
|
||||
local payload = textutils.serialise(todos, { compact = true })
|
||||
rednet.send(sender, payload, PROTOCOL)
|
||||
elseif parts[1] == "edit" then
|
||||
local index = tonumber(parts[2])
|
||||
todos[index].text = parts[3]
|
||||
|
||||
updateUsersTodos(sender)
|
||||
elseif parts[1] == "mark" then
|
||||
local index = tonumber(parts[2])
|
||||
todos[index].marked = true
|
||||
|
||||
updateUsersTodos(sender)
|
||||
elseif parts[1] == "unmark" then
|
||||
local index = tonumber(parts[2])
|
||||
todos[index].marked = false
|
||||
|
||||
updateUsersTodos(sender)
|
||||
elseif parts[1] == "add" then
|
||||
table.insert(todos, {
|
||||
text = parts[2] or "",
|
||||
marked = false
|
||||
})
|
||||
|
||||
updateUsersTodos(sender)
|
||||
elseif parts[1] == "remove" then
|
||||
local index = tonumber(parts[2])
|
||||
table.remove(todos, index)
|
||||
|
||||
updateUsersTodos(sender)
|
||||
elseif parts[1] == "move-up" then
|
||||
local index = tonumber(parts[2])
|
||||
-- TOOD: finish this
|
||||
|
||||
updateUsersTodos(sender)
|
||||
elseif parts[1] == "move-down" then
|
||||
local index = tonumber(parts[2])
|
||||
-- TOOD: finish this
|
||||
|
||||
updateUsersTodos(sender)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
main(...)
|
Loading…
Reference in New Issue
Block a user