136 lines
3.2 KiB
Lua

--[[ Exports a table containing one function: TabbedFile. It wraps a regular Lua file-handle, providing extra functions. Tabs can either be a number of spaces or one tab. It provides the following functions, in addition to (or replacing) the Lua standard ones:
- inc: Increments the tab count by the number given, or by 1 if nothing is given.
- dec: Decrements the tab count by the number given, or by 1 if nothing is given.
- push: Preserves the current tab count.
- pop: Restores the previously preserved tab count.
- write: An indented write; everything is written after the indent.
- writeblock: Takes a single string, breaks it down into multiple lines, and writes each line indented.
- fmt: As string.format followed by an indented write
- fmtblock: As string.format, followed by calling `writeblock`.
- rawfmt: As string.format followed by a NON-indented write.
- rawwrite: hFile:write.
Each call to one of the non-raw writing functions will indent the text.
]]
local members = {}
function members:inc(count)
count = count or 1
rawset(self, "_indent", self._indent + count)
end
function members:dec(count)
count = count or 1
rawset(self, "_indent", self._indent - count)
end
function members:push()
local stack = rawget(self, "_indentStack")
stack[#stack + 1] = rawget(self, "_indent")
end
function members:pop()
local stack = rawget(self, "_indentStack")
assert(#stack > 0, "Tab stack underflow.")
rawset(self, "_indent", stack[#stack])
stack[#stack] = nil
end
function members:fmt(fmt, ...)
self:_Indent()
local str = fmt:format(...)
rawget(self, "_hFile"):write(str)
end
function members:rawfmt(fmt, ...)
local str = fmt:format(...)
rawget(self, "_hFile"):write(str)
end
function members:write(...)
self:_Indent()
rawget(self, "_hFile"):write(...)
end
function members:writeblock(block, ...)
assert(#{...} == 0, "writeblock takes one argument")
for line in block:gmatch("([^\n]*)\n") do
self:write(line, "\n")
end
local last = block:match("\n([^\n]*)$")
if(last and #last ~= 0) then
self:write(last)
end
end
function members:fmtblock(block, ...)
self:writeblock(block:format(...))
end
function members:rawwrite(...)
rawget(self, "_hFile"):write(...)
end
-----------------------------------------------------
-- Standard members
local fileMembers =
{
"close",
"flush",
"lines",
"read",
"seek",
"setvbuf",
"write",
}
for _, fileMem in ipairs(fileMembers) do
if(not members[fileMem]) then
members[fileMem] = function(self, ...)
local hFile = rawget(self, "_hFile")
return hFile[fileMem](hFile, ...)
end
end
end
local metatable = {}
function metatable.__index(self, key)
return members[key]
end
metatable.__newindex = {}
local function IndentFunc(self)
self._hFile:write(string.rep(self._indentStr, self._indent))
end
local function TabbedFile(hFile, style, numSpaces)
numSpaces = numSpaces or 2
local proxy =
{
_hFile = hFile,
_indent = 0,
_Indent = IndentFunc,
_indentStack = {}
}
if(style == "tab") then
proxy._indentStr = "\t"
elseif(style == "space") then
proxy._indentStr = string.rep(" ", numSpaces)
else
error("Unknown indent style " .. style)
end
setmetatable(proxy, metatable)
return proxy
end
return { TabbedFile = TabbedFile }