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 stream.buffer[#stream.buffer+1]=line if stream.capacity<0 then table.remove(stream.buffer,1) stream.capacity=0 end else stream.buffer=stream.buffer..line if stream.capacity<0 then stream.buffer=stream.buffer:sub(-stream.capacity+1) stream.capacity=0 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