1kovand1
-
Публикации
18 -
Зарегистрирован
-
Посещение
Сообщения, опубликованные пользователем 1kovand1
-
-
И еще выдает ...lol: a nil value
-
Так-то работает, но в чём разница?
-
Такой всё равно не обрабатывается (заменил на event.pull)
local com = require"component" local uc = require"unicode" local e = require"event" local term = require"term" local gpu = com.gpu ---------------- buttons = {} function drawButton(name,x,y, w, h, bg, fg, text, onBClick) buttons.name = {} buttons.name[1] = x buttons.name[2] = y buttons.name[3] = w buttons.name[4] = h buttons.name[5] = onBCLick oldbg = gpu.getBackground() oldfg = gpu.getForeground() gpu.setBackground(bg) gpu.setForeground(fg) gpu.fill(x, y, w, h, " ") gpu.set(math.max(x, w)/2 - math.min(x, w)/2 - uc.len(text)/2,math.max(y,h)/2 - math.min(y, h)/2, text) gpu.setBackground(oldbg) gpu.setForeground(oldfg) end local function onClick(_,_, x, y, ...) for name in buttons do print(x.." "..name[1].." "..name[3].." ".. y.." "..name[2].." ".. name[4]) if x >= name[1] and x <= name[3] and y >= name[2] and y <= name[4] then name[5]() end end end local function lol() require"computer".shutdown(false) end e.listen("touch", onClick) local w, h = gpu.getResolution() drawButton("lol", 1, 1, w/2, h/2, 0x00FF00, 0x000000, "lol", lol) while true do e.pull() end -
io.read убирал?
Ошибку to long without yielding выдает
-
Я пишу прогу, которая рисует кнопку, а потом обрабатывает на неё нажатие. Рисовать, то она рисует правильно, но почему-то функция onClick, которая вызывается по ивенту touch не запускается. Вот код:
local com = require"component" local uc = require"unicode" local e = require"event" local term = require"term" local gpu = com.gpu ---------------- buttons = {} function drawButton(name,x,y, w, h, bg, fg, text, onBClick) buttons.name = {} buttons.name[1] = x buttons.name[2] = y buttons.name[3] = w buttons.name[4] = h buttons.name[5] = onBCLick oldbg = gpu.getBackground() oldfg = gpu.getForeground() gpu.setBackground(bg) gpu.setForeground(fg) gpu.fill(x, y, w, h, " ") gpu.set(x,math.max(y,h)/2 - math.min(y, h)/2, text) gpu.setBackground(oldbg) gpu.setForeground(oldfg) end local function onClick(_,_, x, y, ...) for name in buttons do print(x.." "..name[1].." "..name[3].." ".. y.." "..name[2].." ".. name[4]) if x >= name[1] and x <= name[3] and y >= name[2] and y <= name[4] then name[5]() end end end local function lol() require"computer".shutdown(false) end e.listen("touch", onClick) local w, h = gpu.getResolution() drawButton("lol", 1, 1, w/2, h/2, 0x00FF00, 0x000000, "lol", lol) while true do io.read() end -
Теперь я с уверенностью могу сказать что видел всё!
Нет отступов, это ещё цветочки.
Это вообще лишнее. Весь код сплошной ужас.
Попробую написать как надо и догадаться для каких целей тебе это нужно:local event = require("event") local com = require("component") --вообще не знаю зачем в данном коде эта библиотека, ну раз тебе она так нужна пусть будет while true do local out = {event.pull("touch")} --евент ожидается пока не будет получины данные --local out = {event.pull(60,"touch")} --если евент должен срываться при достижении в данном случае 60 сек без отклика, то ставим эту строку вместо предыдущей print(out[1].."\n"..out[2].."\n"..out[3].."\n"..out[4].."\n"..out[5].."\n"..out[6].."\n") --отображаем 6 значений из таблицы if not out[1] then --если захочешь поставить второй вариант евента, который срывает его, то его срыв вызовет выход из цикла break --вместо выхода из цикла можем написать любой код end endВот такой короткий и чёткий код получился.
А если какой-нибудь аргумент будет nil -
Раз уж на то пошло, что такое
ipairs
-
event = require("event")
com = require("component")
while true do
local f,s,t, fo, fi, si = event.pull(60)
event = require("event")
com = require("component")
while true do
local f,s,t, fo, fi, si = event.pull("touch")
if si == nil then
si = "nil"
end
if fi == nil then
fi = "nil"
end
if fo == nil then
fo = "nil"
end
if t == nil then
t = "nil"
end
if s == nil then
s = "nil"
end
if f == nil then
f = "nil"
end
if f ~= "nil" then
print(f.."\n"..s.."\n"..t.."\n"..fo.."\n"..fi.."\n"..si.."\n")
end
end
si = "nil"
end
if fi == nil then
fi = "nil"
end
if fo == nil then
fo = "nil"
end
if t == nil then
t = "nil"
end
if s == nil then
s = "nil"
end
if f == nil then
f = "nil"
end
if f ~= "nil" then
print(f.."\n"..s.."\n"..t.."\n"..fo.."\n"..fi.."\n"..si.."\n")
end
end
-
Что значит "пропускает"? Возвращает любой, не возвращает вообще ничего?Любой возвращает
-
Почему не работает фильтрация , например
event.pull("chat_message")все равно пропускает все эвенты.
-
А то в официальной документации ничего не понятно
-
Просто надо для системки безопасности дома
-
Первый вариант:local event = require "event" function event.shouldInterrupt() return false endПри последующей работе библиотеки event программа не будет прерываться при этом сочетании клавиш.Второй вариант:
Не использовать библиотеку event вообще. Вместо этого получать события так:
local computer = require "computer" while true do local e = computer.pullSignal() -- Далее обработка события endСпасибо большое! Я знал про функцию shouldInterrupt(),
Просто не зналл куда именно ее писать
-
Думаю,ничего объяснять не нужно
-
И еще вопросик, можно ли из значения переменной взять первые несколько символов, а остальные отбросить, например:
input = "ABCDEFGH" через некий код превращается в
output = "ABC"
-
table.red = 14
Если я еще не забыл луа....
Забыл, видимо, там table["red"] = 14
-
Значит мне надо чтобы если в переменной обнаружен(ы) пробел(ы), то она разбивалась на две и более частей (в зависимости от кол-ва пробелов)
Например есть переменная input = "abc def ghi", она через некий код должна превратиться в переменные
output1 = "abc"
output2 = "def"
output3 = "ghi"
P.S нужно для программки на OpenComputers

Как перенаправить стандартный вывод для удаленно запущенных приложений?
в Разные (отсортировать)
Опубликовано: · Изменено пользователем Alex
Я на днях решил написать небольшой прототип проги для удаленного доступа, которая слушает события modem_message, и исполняет их содержимое, перенаправляя выход в ту же сетевую карту.
У меня получился такой код(Полностью рабочий)
local s = require"shell" local e = require"event" local m = require("component").modem m.open(512) env = _G function env.io.stdout:write(...) m.broadcast(512, ...) end while true do args = {e.pull("modem_message")} s.execute(args[6], env) endПотом, недолго думая, я решил вынести это добро в отдельный поток, который создается в дефолтном шелле bin/sh.lua
Вот такое дело у меня получилось
local component = require("component") local computer = require("computer") local event = require("event") local fs = require("filesystem") local process = require("process") local shell = require("shell") local term = require("term") local text = require("text") local unicode = require("unicode") ------------------------------------------------------------------------------- local memoryStream = {} function memoryStream:close() self.closed = true end function memoryStream:seek() return nil, "bad file descriptor" end function memoryStream:read(n) if self.closed then if self.buffer == "" and self.redirect.read then return self.redirect.read:read(n) else return nil -- eof end end if self.buffer == "" then self.args = table.pack(coroutine.yield(table.unpack(self.result))) end local result = string.sub(self.buffer, 1, n) self.buffer = string.sub(self.buffer, n + 1) return result end function memoryStream:write(value) if not self.redirect.write and self.closed then -- if next is dead, ignore all writes if coroutine.status(self.next) ~= "dead" then error("attempt to use a closed stream") end return true end if self.redirect.write then self.redirect.write:write(value) end if not self.closed then self.buffer = self.buffer .. value self.result = table.pack(coroutine.resume(self.next, table.unpack(self.args))) if coroutine.status(self.next) == "dead" then self:close() end if not self.result[1] then error(self.result[2], 0) end table.remove(self.result, 1) end return true end function memoryStream.new() local stream = {closed = false, buffer = "", redirect = {}, result = {}, args = {}} local metatable = {__index = memoryStream, __gc = memoryStream.close, __metatable = "memorystream"} return setmetatable(stream, metatable) end ------------------------------------------------------------------------------- local function expand(value) local result = value:gsub("%$(%w+)", os.getenv):gsub("%$%b{}", function(match) return os.getenv(expand(match:sub(3, -2))) or match end) return result end local function glob(value) if not value:find("*", 1, true) and not value:find("?", 1, true) then -- Nothing to do here. return {expand(value)} end local segments = fs.segments(value) local paths = {value:sub(1, 1) == "/" and "/" or shell.getWorkingDirectory()} for i, segment in ipairs(segments) do local nextPaths = {} local pattern = segment:gsub("*", ".*"):gsub("?", ".") if pattern == segment then -- Nothing to do, concatenate as-is. for _, path in ipairs(paths) do table.insert(nextPaths, fs.concat(path, segment)) end else pattern = "^(" .. pattern .. ")/?$" for _, path in ipairs(paths) do for file in fs.list(path) do if file:match(pattern) then table.insert(nextPaths, fs.concat(path, file)) end end end if #nextPaths == 0 then error("no matches found: " .. segment) end end paths = nextPaths end for i, path in ipairs(paths) do paths[i] = expand(path) end return paths end local function evaluate(value) local init, results = 1, {""} repeat local match = value:match("^%b''", init) if match then -- single quoted string. no variable expansion. match = match:sub(2, -2) init = init + 2 for i, result in ipairs(results) do results[i] = result .. match end else match = value:match('^%b""', init) if match then -- double quoted string. match = match:sub(2, -2) init = init + 2 else -- plaintext? match = value:match("^([^']+)%b''", init) if not match then -- unmatched single quote. match = value:match('^([^"]+)%b""', init) if not match then -- unmatched double quote. match = value:sub(init) end end end local newResults = {} for _, globbed in ipairs(glob(match)) do for i, result in ipairs(results) do table.insert(newResults, result .. globbed) end end results = newResults end init = init + #match until init > #value return results end local function parseCommand(tokens, ...) if #tokens == 0 then return end local program, args = shell.resolveAlias(tokens[1], table.pack(select(2, table.unpack(tokens)))) local eargs = {} program = evaluate(program) for i = 2, #program do table.insert(eargs, program[i]) end local program, reason = shell.resolve(program[1], "lua") if not program then return nil, reason end for i = 1, #args do for _, arg in ipairs(evaluate(args[i])) do table.insert(eargs, arg) end end args = eargs -- Find redirects. local input, output, mode = nil, nil, "write" tokens = args args = {} local function smt(call) -- state metatable factory local function index(_, token) if token == "<" or token == ">" or token == ">>" then return "parse error near " .. token end call(token) return "args" -- default, return to normal arg parsing end return {__index=index} end local sm = { -- state machine for redirect parsing args = setmetatable({["<"]="input", [">"]="output", [">>"]="append"}, smt(function(token) table.insert(args, token) end)), input = setmetatable({}, smt(function(token) input = token end)), output = setmetatable({}, smt(function(token) output = token mode = "write" end)), append = setmetatable({}, smt(function(token) output = token mode = "append" end)) } -- Run state machine over tokens. local state = "args" for i = 1, #tokens do local token = tokens[i] state = sm[state][token] if not sm[state] then return nil, state end end return program, args, input, output, mode end local function parseCommands(command) local tokens, reason = text.tokenize(command) if not tokens then return nil, reason elseif #tokens == 0 then return true end local commands, command = {}, {} for i = 1, #tokens do if tokens[i] == "|" then if #command == 0 then return nil, "parse error near '|'" end table.insert(commands, command) command = {} else table.insert(command, tokens[i]) end end if #command > 0 then -- push tail command table.insert(commands, command) end for i = 1, #commands do commands[i] = table.pack(parseCommand(commands[i])) if commands[i][1] == nil then return nil, commands[i][2] end end return commands end ------------------------------------------------------------------------------- local function execute(env, command, ...) checkArg(1, command, "string") local commands, reason = parseCommands(command) if not commands then return false, reason end if #commands == 0 then return true end -- Piping data between programs works like so: -- program1 gets its output replaced with our custom stream. -- program2 gets its input replaced with our custom stream. -- repeat for all programs -- custom stream triggers execution of 'next' program after write. -- custom stream triggers yield before read if buffer is empty. -- custom stream may have 'redirect' entries for fallback/duplication. local threads, pipes, inputs, outputs = {}, {}, {}, {} for i = 1, #commands do local program, args, input, output, mode = table.unpack(commands[i]) local reason threads[i], reason = process.load(program, env, function() os.setenv("_", program) if input then local file, reason = io.open(shell.resolve(input)) if not file then error("could not open '" .. input .. "': " .. reason, 0) end table.insert(inputs, file) if pipes[i - 1] then pipes[i - 1].stream.redirect.read = file io.input(pipes[i - 1]) else io.input(file) end elseif pipes[i - 1] then io.input(pipes[i - 1]) end if output then local file, reason = io.open(shell.resolve(output), mode == "append" and "a" or "w") if not file then error("could not open '" .. output .. "': " .. reason, 0) end if mode == "append" then io.write("\n") end table.insert(outputs, file) if pipes[i] then pipes[i].stream.redirect.write = file io.output(pipes[i]) else io.output(file) end elseif pipes[i] then io.output(pipes[i]) end io.write('') end, command) if not threads[i] then return false, reason end if i < #commands then pipes[i] = require("buffer").new("rw", memoryStream.new()) pipes[i]:setvbuf("no") end if i > 1 then pipes[i - 1].stream.next = threads[i] pipes[i - 1].stream.args = args end end local args = select(2, table.unpack(commands[1])) for _, arg in ipairs(table.pack(...)) do table.insert(args, arg) end table.insert(args, 1, true) args.n = #args local result = nil for i = 1, #threads do -- Emulate CC behavior by making yields a filtered event.pull() while args[1] and coroutine.status(threads[i]) ~= "dead" do result = table.pack(coroutine.resume(threads[i], table.unpack(args, 2, args.n))) if coroutine.status(threads[i]) ~= "dead" then args = table.pack(pcall(event.pull, table.unpack(result, 2, result.n))) end end if pipes[i] then pcall(pipes[i].close, pipes[i]) end if not result[1] then if type(result[2]) == "table" and result[2].reason == "terminated" then if result[2].code then result[1] = true result.n = 1 else result[2] = "terminated" end elseif type(result[2]) == "string" then result[2] = debug.traceback(threads[i], result[2]) end break end end -- copy env vars from last process; mostly to ensure stuff like cd.lua works local lastVars = rawget(process.info(threads[#threads]).data, "vars") if lastVars then local localVars = process.info().data.vars for k,v in pairs(lastVars) do localVars[k] = v end end for _, input in ipairs(inputs) do input:close() end for _, output in ipairs(outputs) do output:close() end if not args[1] then return false, args[2] end return table.unpack(result, 1, result.n) end local args, options = shell.parse(...) local history = {} local function escapeMagic(text) return text:gsub('[%(%)%.%%%+%-%*%?%[%^%$]', '%%%1') end local function getMatchingPrograms(baseName) local result = {} -- TODO only matching files with .lua extension for now, might want to -- extend this to other extensions at some point? env var? file attrs? if not baseName or #baseName == 0 then baseName = "^(.*)%.lua$" else baseName = "^(" .. escapeMagic(baseName) .. ".*)%.lua$" end for basePath in string.gmatch(os.getenv("PATH"), "[^:]+") do for file in fs.list(basePath) do local match = file:match(baseName) if match then table.insert(result, match) end end end return result end local function getMatchingFiles(basePath, name) local resolvedPath = shell.resolve(basePath) local result, baseName = {} -- note: we strip the trailing / to make it easier to navigate through -- directories using tab completion (since entering the / will then serve -- as the intention to go into the currently hinted one). -- if we have a directory but no trailing slash there may be alternatives if fs.isDirectory(resolvedPath) and name:len() == 0 then baseName = "^(.-)/?$" else baseName = "^(" .. escapeMagic(name) .. ".-)/?$" end for file in fs.list(resolvedPath) do local match = file:match(baseName) if match then table.insert(result, basePath .. match) end end -- (cont.) but if there's only one match and it's a directory, *then* we -- do want to add the trailing slash here. if #result == 1 and fs.isDirectory(result[1]) then result[1] = result[1] .. "/" end return result end local function hintHandler(line, cursor) local line = unicode.sub(line, 1, cursor - 1) if not line or #line < 1 then return nil end local result local prefix, partial = string.match(line, "^(.+%s)(.+)$") local searchInPath = not prefix and not line:find("/") if searchInPath then -- first part and no path, look for programs in the $PATH result = getMatchingPrograms(line) else -- just look normal files local partialPrefix = (partial or line) local name = partialPrefix:gsub("/+", "/") name = name:sub(-1) == '/' and '' or fs.name(name) partialPrefix = partialPrefix:sub(1, -name:len() - 1) result = getMatchingFiles(partialPrefix, name) end local resultSuffix = "" if searchInPath then resultSuffix = " " elseif #result == 1 and result[1]:sub(-1) ~= '/' then resultSuffix = " " end prefix = prefix or "" for i = 1, #result do result[i] = prefix .. result[i] .. resultSuffix end table.sort(result) return result end if #args == 0 and (io.input() == io.stdin or options.i) and not options.c then -- interactive shell. local t = require"thread" function lolo() local s = require"shell" local e = require"event" local m = require("component").modem m.open(512) env = _G function env.io.stdout:write(...) m.broadcast(512, ...) end while true do args = {e.pull("modem_message")} s.execute(args[6], env) end end t.init() t.create(lolo) while true do if not term.isAvailable() then while not term.isAvailable() do event.pull("term_available") end term.clear() end while term.isAvailable() do local foreground = component.gpu.setForeground(0xFF0000) term.write(expand(os.getenv("PS1") or "$ ")) component.gpu.setForeground(foreground) local command = term.read(history, nil, hintHandler) if not command then term.write("exit\n") return -- eof end while #history > (tonumber(os.getenv("HISTSIZE")) or 10) do table.remove(history, 1) end command = text.trim(command) if command == "exit" then return elseif command ~= "" then local result, reason = os.execute(command) if term.getCursor() > 1 then term.write("\n") end if not result then io.stderr:write((reason and tostring(reason) or "unknown error") .. "\n") end end end end elseif #args == 0 and (io.input() ~= io.stdin) then while true do io.write(expand(os.getenv("PS1") or "$ ")) local command = io.read("*l") if not command then io.write("exit\n") end command = text.trim(command) if command == "exit" then return elseif command ~= "" then local result, reason = os.execute(command) if not result then io.stderr:write((reason and tostring(reason) or "unknown error") .. "\n") end end end else -- execute command. local result = table.pack(execute(...)) if not result[1] then error(result[2], 0) end return table.unpack(result, 2) endМой говнокод с 474 по 497 строку
НО! Теперь перенаправляется вывод не только программ, запущенных через удаленный доступ, но так же и программ, запущенных через сам комп
P.S Убедительная просьба по поводу отступов тапками не кидаться