mirror of
https://github.com/NeoFlock/neonucleus.git
synced 2025-09-24 17:13:31 +02:00
132 lines
2.9 KiB
Lua
132 lines
2.9 KiB
Lua
local shell = require("shell")
|
|
|
|
local args, options = shell.parse(...)
|
|
local error_code = 0
|
|
|
|
local function pop(key, convert)
|
|
local result = options[key]
|
|
options[key] = nil
|
|
if result and convert then
|
|
local c = tonumber(result)
|
|
if not c then
|
|
io.stderr:write(string.format("use --%s=n where n is a number\n", key))
|
|
options.help = true
|
|
error_code = 1
|
|
end
|
|
result = c
|
|
end
|
|
return result
|
|
end
|
|
|
|
local bytes = pop('bytes', true)
|
|
local lines = pop('lines', true)
|
|
local quiet = {pop('q'), pop('quiet'), pop('silent')}
|
|
quiet = quiet[1] or quiet[2] or quiet[3]
|
|
local verbose = {pop('v'), pop('verbose')}
|
|
verbose = verbose[1] or verbose[2]
|
|
local help = pop('help')
|
|
|
|
if help or next(options) then
|
|
local invalid_key = next(options)
|
|
if invalid_key then
|
|
invalid_key = string.format('invalid option: %s\n', invalid_key)
|
|
error_code = 1
|
|
else
|
|
invalid_key = ''
|
|
end
|
|
print(invalid_key .. [[Usage: head [--lines=n] file
|
|
Print the first 10 lines of each FILE to stdout.
|
|
For more info run: man head]])
|
|
os.exit(error_code)
|
|
end
|
|
|
|
if #args == 0 then
|
|
args = {'-'}
|
|
end
|
|
|
|
if quiet and verbose then
|
|
quiet = false
|
|
end
|
|
|
|
local function new_stream()
|
|
return
|
|
{
|
|
open=true,
|
|
capacity=math.abs(lines or bytes or 10),
|
|
bytes=bytes,
|
|
buffer=(lines and lines < 0 and {}) or (bytes and bytes < 0 and '')
|
|
}
|
|
end
|
|
|
|
local function close(stream)
|
|
if stream.buffer then
|
|
if type(stream.buffer) == 'table' then
|
|
stream.buffer = table.concat(stream.buffer)
|
|
end
|
|
io.stdout:write(stream.buffer)
|
|
stream.buffer = nil
|
|
end
|
|
stream.open = false
|
|
end
|
|
|
|
local function push(stream, line)
|
|
if not line then
|
|
return close(stream)
|
|
end
|
|
|
|
local cost = stream.bytes and line:len() or 1
|
|
stream.capacity = stream.capacity - cost
|
|
|
|
if not stream.buffer then
|
|
if stream.bytes and stream.capacity < 0 then
|
|
line = line:sub(1,stream.capacity-1)
|
|
end
|
|
io.write(line)
|
|
if stream.capacity <= 0 then
|
|
return close(stream)
|
|
end
|
|
else
|
|
if type(stream.buffer) == 'table' then -- line storage
|
|
stream.buffer[#stream.buffer+1] = line
|
|
if stream.capacity < 0 then
|
|
table.remove(stream.buffer, 1)
|
|
stream.capacity = 0 -- zero out
|
|
end
|
|
else -- byte storage
|
|
stream.buffer = stream.buffer .. line
|
|
if stream.capacity < 0 then
|
|
stream.buffer = stream.buffer:sub(-stream.capacity+1)
|
|
stream.capacity = 0 -- zero out
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
for i=1,#args do
|
|
local arg = args[i]
|
|
local file, reason
|
|
if arg == '-' then
|
|
arg = 'standard input'
|
|
file = io.stdin
|
|
else
|
|
file, reason = io.open(arg, 'r')
|
|
if not file then
|
|
io.stderr:write(string.format([[head: cannot open '%s' for reading: %s]], arg, reason))
|
|
end
|
|
end
|
|
if file then
|
|
if verbose or #args > 1 then
|
|
io.write(string.format('==> %s <==\n', arg))
|
|
end
|
|
|
|
local stream = new_stream()
|
|
|
|
while stream.open do
|
|
push(stream, file:read('*L'))
|
|
end
|
|
|
|
file:close()
|
|
end
|
|
end
|