[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: [ANN] Reader 1.0
- From: Dirk Laurie <dirk.laurie@...>
- Date: Mon, 20 Feb 2017 17:38:07 +0200
Thanks for the responses on my request for string I/0. In particular,
I took a good look at pl.stringio. As always with Steve's modules,
reading the code was a good refresher course in module design.
In my application I don't need more than the equivalent of 'lines',
except that I do need the ability to peek, or alternatively, to put
back a line to be reread after possibly modifying it.
Reader 1.0 is not on a repository, it is attached here. Martin should
be pleased to see there is (briefly) a license and usage example in
the inlined comments, which are formatted to be visible to LDoc
(thus creating external docs) and IHelp. This email serves as the
readme. Self-tests via standalone test system, training course videos
and product site will have to wait for Reader 2.0.
The module returns a reader factory, which constructs a reader
for reading a file, string or list line by line, with rereading ability.
Usage:
reader = require "reader"
rdr = reader(source,position) -- construct the reader
for line, pos in rdr do -- read line if any
...
rdr:reread(line) -- put back (possibly modifed) line for rereading
...
end
-- reader.lua © Dirk Laurie 2017 MIT license as in Lua 5.3.4 source.
--- `reader` object: read and reread lines from file, list or string
-- Usage:
-- rdr = reader(source,position) -- construct the reader
-- for line, pos in rdr do -- read line if any
-- ...
-- rdr:reread(line) -- put back (possibly modifed) line for rereading
-- ...
-- end
return function(source,linepos)
-- Undocumented feature, provided for debugging: if `linepos` is a function,
-- it overrides the line and position routine constructed by default
if type(linepos) ~= 'function' then
assert(not linepos or type(linepos) =='number',
"bad argument #2 to reader, expected number, got "..type(linepos))
if io.type(source)=='file' then
local lines, seek = source:lines(), source:seek("set",linepos or 0)
linepos = function()
local pos = source:seek()
return lines(), pos
end
elseif type(source)=='string' then
local match = source:sub(linepos or 1):gmatch"()([^\n]+)"
linepos = function()
local pos,line = match()
return line,pos
end
elseif type(source)=='table' then
local pos = (linepos or 1)-1
linepos = function()
pos = pos+1
return source[pos],pos
end
else
assert(false,"no default `linepos` defined for type "..type(source))
end
end
----
return setmetatable (
{ line = nil,
pos = nil,
reread = function(rdr,line)
rdr.line = line
end },
{ __call = function(rdr)
local line = rdr.line
if not line then
line, rdr.pos = linepos()
end
rdr.line = nil
return line, rdr.pos
end } )
end