mirror of
https://github.com/MightyPirates/OpenComputers.git
synced 2025-09-14 17:56:34 -04:00
Merge branch 'master-MC1.10' into master-MC1.11
This commit is contained in:
commit
e370a7b264
@ -2,18 +2,17 @@ local shell = require("shell")
|
||||
local fs = require("filesystem")
|
||||
|
||||
local args = shell.parse(...)
|
||||
local ec = 0
|
||||
if #args == 0 then
|
||||
args = {"-"}
|
||||
end
|
||||
|
||||
local input_method, input_param = "read", require("tty").window.width
|
||||
local input_method, input_param = "read", require("tty").getViewport()
|
||||
|
||||
for i = 1, #args do
|
||||
local arg = shell.resolve(args[i])
|
||||
if fs.isDirectory(arg) then
|
||||
io.stderr:write(string.format('cat %s: Is a directory\n', arg))
|
||||
ec = 1
|
||||
os.exit(1)
|
||||
else
|
||||
local file, reason
|
||||
if args[i] == "-" then
|
||||
@ -24,7 +23,7 @@ for i = 1, #args do
|
||||
end
|
||||
if not file then
|
||||
io.stderr:write(string.format("cat: %s: %s\n", args[i], tostring(reason)))
|
||||
ec = 1
|
||||
os.exit(1)
|
||||
else
|
||||
repeat
|
||||
local chunk = file[input_method](file, input_param)
|
||||
@ -36,5 +35,3 @@ for i = 1, #args do
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return ec
|
||||
|
@ -1,304 +1,99 @@
|
||||
local keyboard = require("keyboard")
|
||||
local shell = require("shell")
|
||||
local term = require("term") -- using term for negative scroll feature
|
||||
local text = require("text")
|
||||
local unicode = require("unicode")
|
||||
local computer = require("computer")
|
||||
local tx = require("transforms")
|
||||
|
||||
if not io.output().tty then
|
||||
return loadfile(shell.resolve("cat", "lua"), "bt", _G)(...)
|
||||
end
|
||||
|
||||
local args = shell.parse(...)
|
||||
if #args > 1 then
|
||||
io.write("Usage: more <filename>\n")
|
||||
io.write("Usage: less <filename>\n")
|
||||
io.write("- or no args reads stdin\n")
|
||||
return 1
|
||||
end
|
||||
local arg = args[1] or "-"
|
||||
|
||||
local initial_offset
|
||||
|
||||
-- test validity of args
|
||||
do
|
||||
if arg == "-" then
|
||||
if not io.stdin then
|
||||
io.stderr:write("this process has no stdin\n")
|
||||
return 1
|
||||
end
|
||||
-- stdin may not be core_stdin
|
||||
initial_offset = io.stdin:seek("cur")
|
||||
else
|
||||
local file, reason = io.open(shell.resolve(arg))
|
||||
if not file then
|
||||
io.stderr:write(reason,'\n')
|
||||
return 1
|
||||
end
|
||||
initial_offset = file:seek("cur")
|
||||
file:close()
|
||||
end
|
||||
local cat_cmd = table.concat({"cat", ...}, " ")
|
||||
if not io.output().tty then
|
||||
return os.execute(cat_cmd)
|
||||
end
|
||||
|
||||
local width, height = term.getViewport()
|
||||
local max_display = height - 1
|
||||
term.clear()
|
||||
|
||||
-- mgr is the data manager, it keeps track of what has been loaded
|
||||
-- keeps a reasonable buffer, and keeps track of file handles
|
||||
local mgr
|
||||
mgr =
|
||||
{
|
||||
lines = {}, -- current buffer
|
||||
chunk, -- temp from last read line that hasn't finished wrapping
|
||||
lines_released = 0,
|
||||
can_seek = initial_offset,
|
||||
capacity = math.max(1, math.min(max_display * 10, computer.freeMemory() / 2 / width)),
|
||||
size = 0,
|
||||
file = nil,
|
||||
path = arg ~= "-" and shell.resolve(arg) or nil,
|
||||
open = function()
|
||||
mgr.file = mgr.path and io.open(mgr.path) or io.stdin
|
||||
end,
|
||||
top_of_file = max_display,
|
||||
total_lines = nil, -- nil means unknown
|
||||
latest_line = nil, -- used for status improvements
|
||||
rollback = function()
|
||||
if not mgr.can_seek then
|
||||
return false
|
||||
end
|
||||
if not mgr.file then
|
||||
mgr.open()
|
||||
elseif not mgr.file:seek("set", 0) then
|
||||
mgr.close()
|
||||
return false
|
||||
end
|
||||
mgr.lines_released = 0
|
||||
mgr.lines = {}
|
||||
mgr.size = 0
|
||||
return true
|
||||
end,
|
||||
at = function(line_number)
|
||||
local index = line_number - mgr.lines_released
|
||||
if index < 1 then
|
||||
index = index + mgr.capacity
|
||||
if #mgr.lines ~= mgr.capacity or index <= mgr.size then
|
||||
return nil
|
||||
end
|
||||
elseif index > mgr.size then
|
||||
return nil
|
||||
end
|
||||
return mgr.lines[index] -- cached
|
||||
end,
|
||||
load = function(line_number)
|
||||
local index = line_number - mgr.lines_released
|
||||
if mgr.total_lines and mgr.total_lines < line_number then
|
||||
return nil
|
||||
end
|
||||
if mgr.at(line_number) then
|
||||
return true
|
||||
end
|
||||
-- lines[index] is line (lines_released + index) in the file
|
||||
-- thus index == line_number - lines_released
|
||||
if index <= 0 then
|
||||
-- we have previously freed some of the buffer, and now the user wants it back
|
||||
if not mgr.rollback() then
|
||||
-- TODO how to nicely fail if can_seek == false
|
||||
-- or if no more buffers
|
||||
error("cannot load prior data")
|
||||
end
|
||||
return mgr.load(line_number) -- retry
|
||||
end
|
||||
if mgr.read_next() then
|
||||
return mgr.load(line_number) -- retry
|
||||
end
|
||||
-- ran out of file, could not reach line_number
|
||||
end,
|
||||
write = function(line_number)
|
||||
local line = mgr.at(line_number)
|
||||
if not line then return false end
|
||||
term.write(line)
|
||||
end,
|
||||
close = function()
|
||||
if mgr.file then
|
||||
mgr.file:close()
|
||||
mgr.file = nil
|
||||
end
|
||||
end,
|
||||
last = function()
|
||||
-- return the last line_number available right now in the cache
|
||||
return mgr.size + mgr.lines_released
|
||||
end,
|
||||
check_capacity = function(release)
|
||||
-- if we have reached capacity
|
||||
if mgr.size >= mgr.capacity then
|
||||
if release then
|
||||
mgr.lines_released = mgr.lines_released + mgr.size
|
||||
mgr.size = 0
|
||||
end
|
||||
return true
|
||||
end
|
||||
end,
|
||||
insert = function(line)
|
||||
if mgr.check_capacity() then return false end
|
||||
mgr.size = mgr.size + 1
|
||||
mgr.lines[mgr.size] = line
|
||||
-- latest_line is not used for computation, just for status reports
|
||||
mgr.latest_line = math.max(mgr.latest_line or 0, mgr.size + mgr.lines_released)
|
||||
return true
|
||||
end,
|
||||
read_next = function()
|
||||
-- total_lines indicates we've reached the end previously
|
||||
-- but have we just prior to this reached the end?
|
||||
if mgr.last() == mgr.total_lines then
|
||||
-- then there is no more after that point
|
||||
return nil
|
||||
end
|
||||
if not mgr.file then
|
||||
mgr.open()
|
||||
end
|
||||
mgr.check_capacity(true)
|
||||
if not mgr.chunk then
|
||||
mgr.chunk = mgr.file:read("*l")
|
||||
if not mgr.chunk then
|
||||
mgr.total_lines = mgr.size + mgr.lines_released -- now file length is known
|
||||
mgr.close()
|
||||
end
|
||||
end
|
||||
while mgr.chunk do
|
||||
local wrapped, next = text.wrap(text.detab(mgr.chunk), width, width)
|
||||
-- insert fails if capacity is full
|
||||
if not mgr.insert(wrapped) then
|
||||
return mgr.last()
|
||||
end
|
||||
mgr.chunk = next
|
||||
end
|
||||
|
||||
return mgr.last()
|
||||
end,
|
||||
scroll = function(num)
|
||||
if num < 0 then
|
||||
num = math.max(num, mgr.top_of_file)
|
||||
if num >= 0 then
|
||||
return true -- nothing to scroll
|
||||
end
|
||||
end
|
||||
|
||||
term.setCursor(1, height)
|
||||
local y = height
|
||||
term.clearLine()
|
||||
|
||||
if num < 0 then
|
||||
term.scroll(num) -- push text down
|
||||
mgr.top_of_file = mgr.top_of_file - num
|
||||
y = 1
|
||||
term.setCursor(1, y) -- ready to write lines above
|
||||
num = -num -- now print forward
|
||||
end
|
||||
|
||||
local range
|
||||
while num > 0 do
|
||||
-- trigger load of data if needed
|
||||
local line_number = y - mgr.top_of_file
|
||||
|
||||
if not mgr.load(line_number) then -- nothing more to read from the file
|
||||
return range ~= nil -- first time it is nil
|
||||
end
|
||||
|
||||
-- print num range of what is available, scroll to show it (if bottom of screen)
|
||||
range = math.min(num, mgr.last() - line_number + 1)
|
||||
|
||||
if y == height then
|
||||
range = math.min(range, max_display)
|
||||
term.scroll(range)
|
||||
y = y - range
|
||||
term.setCursor(1, y)
|
||||
mgr.top_of_file = mgr.top_of_file - range
|
||||
end
|
||||
|
||||
for i=1,range do
|
||||
mgr.write(line_number + i - 1)
|
||||
term.setCursor(1, y + i)
|
||||
end
|
||||
y = y + range
|
||||
|
||||
num = num - range
|
||||
end
|
||||
|
||||
return true
|
||||
end,
|
||||
print_status = function()
|
||||
local first = mgr.top_of_file >= 1 and 1 or 1 - mgr.top_of_file
|
||||
local perc = not mgr.total_lines and "--" or tostring((max_display - mgr.top_of_file) / mgr.total_lines * 100):gsub("%..*","")
|
||||
local last_plus = mgr.total_lines and "" or "+"
|
||||
local status = string.format("%s lines %d-%d/%s %s%%", mgr.path or "-", first, max_display - mgr.top_of_file, tostring(mgr.total_lines or mgr.latest_line)..last_plus, perc)
|
||||
|
||||
local gpu = term.gpu()
|
||||
local sf, sb = gpu.setForeground, gpu.setBackground
|
||||
local b_color, b_is_palette = gpu.getBackground()
|
||||
local f_color, f_is_palette = gpu.getForeground()
|
||||
sf(b_color, b_is_palette)
|
||||
sb(f_color, f_is_palette)
|
||||
term.write(status)
|
||||
sb(b_color, b_is_palette)
|
||||
sf(f_color, f_is_palette)
|
||||
local preader = io.popen(cat_cmd)
|
||||
local buffer = setmetatable({}, {__index = function(tbl, index)
|
||||
if type(index) ~= "number" or index < 1 then return end
|
||||
while #tbl < index do
|
||||
local line = preader:read()
|
||||
if not line then return end
|
||||
table.insert(tbl, line)
|
||||
end
|
||||
}
|
||||
return tbl[index]
|
||||
end})
|
||||
|
||||
local function update(num)
|
||||
-- unexpected
|
||||
if num == 0 then
|
||||
return
|
||||
local index = 1
|
||||
|
||||
local _, height = term.getViewport()
|
||||
local status = ":"
|
||||
|
||||
local function goback(n)
|
||||
n = math.min(index - height, n)
|
||||
if n <= 0 then return end -- make no back scroll, we're at the top
|
||||
term.scroll(-n)
|
||||
index = index - n
|
||||
for y = 1, math.min(height - 1, n) do
|
||||
term.setCursor(1, y)
|
||||
print(buffer[index - height + y])
|
||||
end
|
||||
|
||||
-- if this a positive direction, and we didn't previously know this was the end of the stream, give the user a once chance
|
||||
local end_is_known = mgr.total_lines
|
||||
-- clear buttom line, for status
|
||||
local ok = mgr.scroll(num or max_display)
|
||||
|
||||
-- print status
|
||||
term.setCursor(1, height)
|
||||
-- we have to clear again in case we scrolled up
|
||||
term.clearLine()
|
||||
mgr.print_status()
|
||||
return not end_is_known or ok
|
||||
end
|
||||
|
||||
if not update() then
|
||||
return
|
||||
local function goforward(n)
|
||||
if not buffer[index] then return end -- nothing to do
|
||||
for test_index = index, index + n do
|
||||
if not buffer[test_index] then
|
||||
n = math.min(n, test_index - index)
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
term.clearLine()
|
||||
term.scroll(n)
|
||||
if n >= height then
|
||||
index = index + (n - height) + 1
|
||||
n = height - 1
|
||||
end
|
||||
term.setCursor(1, height - n)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
while true do
|
||||
local ename, address, char, code, dy = term.pull()
|
||||
local num
|
||||
if ename == "scroll" then
|
||||
if dy < 0 then
|
||||
num = 3
|
||||
else
|
||||
num = -3
|
||||
end
|
||||
elseif ename == "key_down" then
|
||||
num = 0
|
||||
if code == keyboard.keys.q or code == keyboard.keys.d and keyboard.isControlDown() then
|
||||
break
|
||||
elseif code == keyboard.keys.space or code == keyboard.keys.pageDown then
|
||||
num = max_display
|
||||
elseif code == keyboard.keys.pageUp then
|
||||
num = -max_display
|
||||
elseif code == keyboard.keys.enter or code == keyboard.keys.down then
|
||||
num = 1
|
||||
elseif code == keyboard.keys.up then
|
||||
num = -1
|
||||
elseif code == keyboard.keys.home then
|
||||
num = -math.huge
|
||||
local _, y = term.getCursor()
|
||||
local print_next_line = true
|
||||
if y == height then
|
||||
print_next_line = false
|
||||
term.clearLine()
|
||||
io.write(status)
|
||||
local _, _, _, code = term.pull("key_down")
|
||||
if code == keyboard.keys.q then
|
||||
term.clearLine()
|
||||
os.exit(1) -- abort
|
||||
elseif code == keyboard.keys["end"] then
|
||||
num = math.huge
|
||||
print_next_line = goforward(math.huge)
|
||||
elseif code == keyboard.keys.space or code == keyboard.keys.pageDown then
|
||||
print_next_line = goforward(height - 1)
|
||||
elseif code == keyboard.keys.enter or code == keyboard.keys.down then
|
||||
print_next_line = goforward(1)
|
||||
elseif code == keyboard.keys.up then
|
||||
goback(1)
|
||||
elseif code == keyboard.keys.pageUp then
|
||||
goback(height - 1)
|
||||
end
|
||||
elseif ename == "interrupted" then
|
||||
break
|
||||
end
|
||||
if num then
|
||||
update(num)
|
||||
if print_next_line then
|
||||
local line = buffer[index]
|
||||
if line then
|
||||
print(line)
|
||||
index = index + 1
|
||||
else
|
||||
term.setCursor(1, height)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
term.clearLine()
|
||||
|
@ -1,7 +1,6 @@
|
||||
local buffer = require("buffer")
|
||||
local keyboard = require("keyboard")
|
||||
local shell = require("shell")
|
||||
local tty = require("tty")
|
||||
local term = require("term")
|
||||
|
||||
local args = shell.parse(...)
|
||||
if #args > 1 then
|
||||
@ -10,48 +9,36 @@ if #args > 1 then
|
||||
return 1
|
||||
end
|
||||
|
||||
local function clear_line()
|
||||
tty.window.x = 1 -- move cursor to start of line
|
||||
io.write("\27[2K") -- clear line
|
||||
local cat_cmd = table.concat({"cat", ...}, " ")
|
||||
if not io.output().tty then
|
||||
return os.execute(cat_cmd)
|
||||
end
|
||||
|
||||
if io.output().tty then
|
||||
io.write("\27[2J\27[H")
|
||||
term.clear()
|
||||
|
||||
local intercept_active = true
|
||||
local original_stream = io.stdout.stream
|
||||
local custom_stream = setmetatable({
|
||||
scroll = function(...)
|
||||
local _, height, _, _, _, y = tty.getViewport()
|
||||
local lines_below = height - y
|
||||
if intercept_active and lines_below < 1 then
|
||||
intercept_active = false
|
||||
original_stream.scroll(-lines_below) -- if zero no scroll action is made [good]
|
||||
tty.setCursor(1, height) -- move to end
|
||||
clear_line()
|
||||
io.write(":") -- status
|
||||
local _, _, _, code = original_stream:pull(nil, "key_down") -- nil timeout is math.huge
|
||||
if code == keyboard.keys.q then
|
||||
clear_line()
|
||||
os.exit(1) -- abort
|
||||
elseif code == keyboard.keys["end"] then
|
||||
io.stdout.stream.scroll = nil -- remove handler
|
||||
elseif code == keyboard.keys.space or code == keyboard.keys.pageDown then
|
||||
io.write("\27[2J\27[H") -- clear whole screen, get new page drawn; move cursor to 1,1
|
||||
elseif code == keyboard.keys.enter or code == keyboard.keys.down then
|
||||
clear_line() -- remove status bar
|
||||
original_stream.scroll(1) -- move everything up one
|
||||
tty.setCursor(1, height - 1)
|
||||
end
|
||||
intercept_active = true
|
||||
end
|
||||
return original_stream.scroll(...)
|
||||
local preader = io.popen(cat_cmd)
|
||||
local intercept = true
|
||||
while true do
|
||||
local _, height, _, _, _, y = term.getViewport()
|
||||
if intercept and y == height then
|
||||
term.clearLine()
|
||||
io.write(":") -- status
|
||||
::INPUT::
|
||||
local _, _, _, code = term.pull("key_down")
|
||||
if code == keyboard.keys.q then
|
||||
term.clearLine()
|
||||
os.exit(1) -- abort
|
||||
elseif code == keyboard.keys["end"] then
|
||||
intercept = false
|
||||
elseif code == keyboard.keys.space or code == keyboard.keys.pageDown then
|
||||
term.clear() -- clear whole screen, get new page drawn; move cursor to 1,1
|
||||
elseif code == keyboard.keys.enter or code == keyboard.keys.down then
|
||||
term.clearLine() -- remove status bar
|
||||
term.scroll(1) -- move everything up one
|
||||
term.setCursor(1, height - 1)
|
||||
else
|
||||
goto INPUT
|
||||
end
|
||||
}, {__index=original_stream})
|
||||
|
||||
local custom_output_buffer = buffer.new("w", custom_stream)
|
||||
custom_output_buffer:setvbuf("no")
|
||||
io.output(custom_output_buffer)
|
||||
end
|
||||
print(preader:read() or os.exit())
|
||||
end
|
||||
|
||||
return loadfile(shell.resolve("cat", "lua"))(...)
|
||||
|
@ -30,6 +30,7 @@ if #args == 0 then
|
||||
if command == "exit" then
|
||||
return
|
||||
elseif command ~= "" then
|
||||
tty.window.cursor = nil -- the spawned process should use its own cursor
|
||||
local result, reason = sh.execute(_ENV, command)
|
||||
if not result then
|
||||
io.stderr:write((reason and tostring(reason) or "unknown error") .. "\n")
|
||||
|
@ -69,6 +69,14 @@ end
|
||||
function core_cursor.vertical:echo(arg, num)
|
||||
local win = tty.window
|
||||
local gpu = win.gpu
|
||||
|
||||
-- we should not use io.write
|
||||
-- the cursor should echo to the stream it is reading from
|
||||
-- this makes sense because a process may redirect its io
|
||||
-- but a cursor reading from a given stdin tty should also
|
||||
-- echo to that same stream
|
||||
local out = io.stdin.stream
|
||||
|
||||
if not gpu then return end
|
||||
win.nowrap = self.nowrap
|
||||
if arg == "" then -- special scroll request
|
||||
@ -76,7 +84,7 @@ function core_cursor.vertical:echo(arg, num)
|
||||
if x > width then
|
||||
win.x = ((x - 1) % width) + 1
|
||||
win.y = y + math.floor(x / width)
|
||||
io.write("") -- tty.stream:write knows how to scroll vertically
|
||||
out:write("") -- tty.stream:write knows how to scroll vertically
|
||||
x, y = win.x, win.y
|
||||
end
|
||||
if x <= 0 or y <= 0 or y > win.height or not gpu then return end
|
||||
@ -108,25 +116,25 @@ function core_cursor.vertical:echo(arg, num)
|
||||
if not char[1] then return false end
|
||||
self.blinked = true
|
||||
if not arg then
|
||||
io.write("\0277")
|
||||
out:write("\0277")
|
||||
char.saved = win.saved
|
||||
gpu.setForeground(char[4] or char[2], not not char[4])
|
||||
gpu.setBackground(char[5] or char[3], not not char[5])
|
||||
end
|
||||
io.write("\0277", "\27[7m", char[1], "\0278")
|
||||
out:write("\0277\27[7m"..char[1].."\0278")
|
||||
elseif (arg and self.blinked) or (arg == false and char) then
|
||||
self.blinked = false
|
||||
gpu.set(win.x + win.dx, win.y + win.dy, char[1])
|
||||
if not arg then
|
||||
win.saved = char.saved
|
||||
io.write("\0278")
|
||||
out:write("\0278")
|
||||
char = nil
|
||||
end
|
||||
end
|
||||
self.char_at_cursor = char
|
||||
return true
|
||||
end
|
||||
return io.write(arg)
|
||||
return out:write(arg)
|
||||
end
|
||||
|
||||
function core_cursor.vertical:handle(name, char, code)
|
||||
|
@ -85,7 +85,7 @@ function sh.internal.openCommandRedirects(redirects)
|
||||
|
||||
if type(to_io) == "number" then -- io to io
|
||||
-- from_io and to_io should be numbers
|
||||
ios[from_io] = ios[to_io]
|
||||
ios[from_io] = io.dup(ios[to_io])
|
||||
else
|
||||
-- to_io should be a string
|
||||
local file, reason = io.open(shell.resolve(to_io), mode)
|
||||
|
@ -108,6 +108,19 @@ function io.write(...)
|
||||
return io.output():write(...)
|
||||
end
|
||||
|
||||
function io.dup(fd)
|
||||
return setmetatable({
|
||||
close = function(self) self._closed = true end,
|
||||
}, {__index = function(_, key)
|
||||
local fd_value = fd[key]
|
||||
if type(fd_value) ~= "function" then return fd_value end
|
||||
return function(self, ...)
|
||||
if self._closed then return nil, "closed stream" end
|
||||
return fd_value(fd, ...)
|
||||
end
|
||||
end})
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
return io
|
||||
|
@ -81,21 +81,18 @@ local pipe_stream =
|
||||
if coroutine.status(self.next) == "suspended" then
|
||||
self:continue()
|
||||
end
|
||||
self.redirect = {}
|
||||
end,
|
||||
seek = function()
|
||||
return nil, "bad file descriptor"
|
||||
end,
|
||||
write = function(self, value)
|
||||
if not self.redirect[1] and self.closed then
|
||||
if self.closed then
|
||||
-- if next is dead, ignore all writes
|
||||
if coroutine.status(self.next) ~= "dead" then
|
||||
io.stderr:write("attempt to use a closed stream\n")
|
||||
os.exit(1)
|
||||
end
|
||||
elseif self.redirect[1] then
|
||||
return self.redirect[1]:write(value)
|
||||
elseif not self.closed then
|
||||
else
|
||||
self.buffer = self.buffer .. value
|
||||
return self:continue(true)
|
||||
end
|
||||
@ -105,11 +102,7 @@ local pipe_stream =
|
||||
if self.closed then
|
||||
return nil -- eof
|
||||
end
|
||||
if self.redirect[0] then
|
||||
-- popen could be using this code path
|
||||
-- if that is the case, it is important to leave stream.buffer alone
|
||||
return self.redirect[0]:read(n)
|
||||
elseif self.buffer == "" then
|
||||
if self.buffer == "" then
|
||||
-- the pipe_stream write resume is waiting on this process B (A|B) to yield
|
||||
-- yield here requests A to output again. However, B may elsewhere want a
|
||||
-- natural yield (i.e. for events). To differentiate this yield from natural
|
||||
@ -139,7 +132,7 @@ function pipe.buildPipeChain(progs)
|
||||
|
||||
local piped_stream
|
||||
if i < #progs then
|
||||
local handle = setmetatable({redirect = {rawget(pio, 1)},buffer = ""}, {__index = pipe_stream})
|
||||
local handle = setmetatable({buffer = ""}, {__index = pipe_stream})
|
||||
process.closeOnExit(handle, proc)
|
||||
piped_stream = buffer.new("rw", handle)
|
||||
piped_stream:setvbuf("no", 1024)
|
||||
@ -147,7 +140,6 @@ function pipe.buildPipeChain(progs)
|
||||
end
|
||||
|
||||
if prev_piped_stream then
|
||||
prev_piped_stream.stream.redirect[0] = rawget(pio, 0)
|
||||
prev_piped_stream.stream.next = thread
|
||||
pio[0] = prev_piped_stream
|
||||
end
|
||||
|
@ -97,7 +97,9 @@ function process.load(path, env, init, name)
|
||||
parent = p,
|
||||
instances = setmetatable({}, {__mode="v"}),
|
||||
}
|
||||
setmetatable(new_proc.data.io, {__index=p.data.io})
|
||||
for i,fd in pairs(p.data.io) do
|
||||
new_proc.data.io[i] = io.dup(fd)
|
||||
end
|
||||
setmetatable(new_proc.data, {__index=p.data})
|
||||
process.list[thread] = new_proc
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user