This is an interesting technique to use Iguana itself to serve the documentation of it’s own API (see comments in the code). If you are interested in this you may also want to checkout using _G to discover the entire API of the Translator. Also see the Iguana Translator modules reference.
If you are curious about some ideas to document your own interfaces you might want to check out documenting an HL7 interface.
First make a channel with a Translator component (a To Translator is easiest).
Paste in the following code:
-- fetch help info from all functions
-- by calling them with no params and reaping the error message
-- PROBLEM some functions are missed because they have no params
-- eg iguana.isTest() and json.createObject()
-- HACK call that tries to guarantee invalid params
-- 2ND HACK in response to error introduced by first caused by
-- logic added to identify error and give improved feedback...
local G=util.guid(128)
local function createHelp(Input)
print(G)
local out = {}
for i,v in pairs(Input) do
if (type(v) == 'function') then
-- some functions are missed = have no params
--local test,err = pcall(v)
-- HACK try to guarantee invalid call
local test,err = pcall(v,{G=1},G,{G=G},asdf,'ÄdÉfÍ',[[n#@]]) --HACK
print(err)
if err:find("@@Unknown parameter: 'G'") then -- 2ND HACK
test,err = pcall(v)
end
if not test then
local sentinel = '%@%@%<%>%<%>ifware%-error%<%>%<%>%@%@'
print(sentinel)
local err_fixed = err:gsub(sentinel,'')
out[i] = tostring(err_fixed)
end
elseif (type(v) == 'table') then
print(v)
local NextSet = createHelp(v)
if (#NextSet) then out[i] = NextSet end
end
end
return out
end
-- similar to pairs(), but gives a sorted set
local function pairsByKeys (t, f)
local a = {}
for n in pairs(t) do table.insert(a, n) end
table.sort(a, f)
local i = 0 -- iterator variable
local iter = function () -- iterator function
i = i + 1
if a[i] == nil then return nil
else return a[i], t[a[i]]
end
end
return iter
end
-- writes out several files, in a hierachical fashion
local function writeHelpFiles(Doc,Key,BaseDir)
-- write this, and links
local out = '<HTML><TITLE>'..Key..'</TITLE><BODY>'
out = out..'<H3>'..Key..'</H3><UL>'
for i,v in pairsByKeys(Doc) do
out = out..'<li>'
if type(v) == 'table' then
out = out..'<a href="'..Key..'.'..i..'.html">'..i..'</a>'
--do one level down
out = out..'<table>'
for j,k in pairsByKeys(v) do
local summary = ''
if type(k) == 'string' then
local pattern = '([^n]*)(.*)'
_,_,summary = k:find(pattern)
end
out = out..'<tr><td width="20"></td><td width="80"><a href="'
..Key..'.'..i..'.html#'..j..'">'..j..'</a></td><td>'..summary..'</td></tr>'
end
out = out..'</table>'
writeHelpFiles(v,Key..'.'..i,BaseDir)
else
out = out..'<a name="'..i..'"><b>'..i..'</b></a><br><pre>'..v..'</pre>'
end
out = out..'</li>'
end
out = out..'</UL></BODY></HTML>'
local fd = io.open(BaseDir..''..Key..'.html','wb')
fd:write(out)
fd:close()
end
-- writes everything to a single html string
local function writeAll(Doc,Key,Parent)
Parent = Parent or 'base'
local out = ''
out = out..'<a name="'..Parent..'.'..Key..'"><H2>'..Key..'</H2></a><UL>'
for i,v in pairsByKeys(Doc) do
out = out..'<li>'
if type(v) == 'table' then
--do sub levels
out = out..writeAll(v,i,Key)
else
out = out..'<a name="'..Parent..'.'..Key..'.'..i..'"><b>'..i..'</b></a><br><pre>'..v..'</pre>'
end
out = out..'</li>'
end
out = out..'</UL>'
return out
end
-- writes a table of contents for the top of the OneHelpFile
local function writeToc(Doc,Key,Parent)
Parent = Parent or 'base'
local out = ''
out = out..'<a href="#'..Parent..'.'..Key..'">'..Key..'</a><UL>'
for i,v in pairsByKeys(Doc) do
out = out..'<li>'
if type(v) == 'table' then
--do sub levels
out = out..writeToc(v,i,Key)
else
local summary = ''
local pattern = '([^n]*)(.*)'
_,_,summary = v:find(pattern)
out = out..'<a href="#'..Parent..'.'..Key..'.'..i..'">'..i..'</a> : '..summary
end
out = out..'</li>'
end
out = out..'</UL>'
return out
end
-- write a single file
local function writeOneHelpFile(Doc,Key,BaseDir)
local out = '<HTML><TITLE>'..Key..'</TITLE><BODY>'
out = out..writeToc(Doc,Key)
out = out..writeAll(Doc,Key)
out = out..'</UL></BODY></HTML>'
local fd = io.open(BaseDir..''..Key..'_all.html','wb')
fd:write(out)
fd:close()
end
local function deepcopy(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, getmetatable(object))
end
return _copy(object)
end
-- copy _G and remove Lua stuff so only Iguan modules remain
local function getIguanaModules()
local my_G=deepcopy(_G)
-- remove Lua stuff
my_G.xpcall=nil
my_G.string=nil
my_G.tostring=nil
my_G.package=nil
my_G.os=nil
my_G.unpack=nil
my_G.require=nil
my_G.print=nil
my_G.getfenv=nil
my_G.next=nil
my_G.assert=nil
my_G.setmetatable=nil
my_G.setfenv=nil
my_G.tonumber=nil
my_G.gcinfo=nil
my_G.io=nil
my_G.rawequal=nil
my_G._VERSION=nil
my_G.collectgarbage=nil
my_G.debug=nil
my_G.getmetatable=nil
my_G.collectgarbage=nil
my_G.module=nil
my_G.collectgarbage=nil
my_G.cache=nil
my_G.rawset=nil
my_G.math=nil
my_G.load=nil
my_G.pcall=nil
my_G.table=nil
my_G.newproxy=nil
my_G.type=nil
my_G.coroutine=nil
my_G._G=nil
my_G.select=nil
my_G.pairs=nil
my_G.rawget=nil
my_G.loadstring=nil
my_G.ipairs=nil
my_G.main=nil
my_G.dofile=nil
my_G.IntellisenseObject=nil
my_G.error=nil
my_G.loadfile=nil
my_G._=nil
return my_G
end
-- remove known Iguana modules so new ones can be identified
-- and then can be documented
local function getNewIguanaModules()
local my_G=getIguanaModules()
--remove known Iguana modules
my_G.ack=nil
my_G.queue=nil
my_G.net=nil
my_G.iguana=nil
my_G.util=nil
my_G.xml=nil
my_G.db=nil
my_G.node=nil
my_G.hl7=nil
my_G.x12=nil
my_G.json=nil
my_G.chm=nil
my_G.filter=nil
return my_G
end
function main(Data)
-- list out all namespaces in our code that we want to print
-- note that this won't work with the _G table, because some
-- functions will work with no parameters, and proceed to block indefinitely
-- so we narrow down what we want to print
-- HACK: see createHelp() - now uses weird params to catch *no-param* fn()s
-- does not work with _G as it overflows the stack
-- NOTE: use table annotation with print(_G) to inspect global environment
-- use it to check for new modules and
-- check you have printed out all functions in a module
-- get all Iguana Modules
getIguanaModules()
-- get all NEW Iguana Modules
-- add to list below
getNewIguanaModules()
local ifware = {
-- remember to add new Iguana modules to list (see above)
--['ack']=ack,
--['xml']=xml,
--['util'] = util,
--['queue'] = queue,
--['iguana'] = iguana, -- iguana.isTest() has no params
['node']=node,
--['x12']=x12,
--['chm']=chm
--['hl7'] = hl7,
--['db'] = db,
--['net'] = net,
--['json'] = json, -- json.createObject() has no params
--['filter'] = filter,
--['NEW modules'] = getNewIguanaModules(),
--['ALL modules'] = getIguanaModules(),
--['_G']=[_G] -- overflows the the stack - try it
}
print(_G) -- inspect global environment table
local output_dir = [[c:program filesiNTERFACEWAREiguanaweb_docsdocs]]
local base_name = 'iguana'
-- collect up all the help info
local out = createHelp(ifware,base_name)
--write out a hierachical set of html files
writeHelpFiles(out,base_name,output_dir)
--write a single html file called <base_name>_all.html
writeOneHelpFile(out,base_name,output_dir)
end
You may have some errors initially, just turn off annotations for now.
Then in the main function:
- Modify the base directory so that it points to the iguana installation location. E.g., if you have installed Iguana in c:iguana, change the base directory to ‘c:iguanaweb_docsdocs’
- Go to the install directory, and there will be a web_docs subdirectory. In web_docs, make a docs folder.
Now turn on annotations, and make sure that it runs with no errors.
Now go back to the dashboard, and go to
http://<my ip>:<my iguana port>/docs/iguana_all.html
or
http://<my ip>:<my iguana port>/docs/iguana.html
or you can just open the files from the doc directory…
And you should see the API’s documented!