lua-users home
lua-l archive

a script to simulate lua man pages

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Dear Lua Lovers,
I use Lua only episodically, and I hate having to look up API
functions every time I want to do something. If only there
were man pages, I could just type
 man lua_gettable
and everything would be good. But there are no man pages :-(
Do not fear! An hour of hacking solves the problem.
Attached is a script that goes through the HTML version
of the Lua manual and extracts documentation relevant
to functions by name (and more besides). Some examples
you can try include
 luahelp gettable
 luahelp expressions
 luahelp metatable
and much more besides. For guidance, run the script with no arguments.
Be warned that you will need to edit two variables!
The script needs to know where the manual is, and it
needs a pager that can display HTML read from standard
input. The defaults should work on Debian linux,
provided you have lynx installed.
Under 200 lines of goodness! Enjoy!
Norman
#!/usr/bin/env lua50
--[[--------------------------------------------------------------
This script reads the HTML version of the lua manual and pulls out
a short section containing the documentation you hoped for :-)
It is meant to work around the lack of man pages for lua.
For examples, run the script with no arguments.
It requires you two edit two variables:
 manual Location of the manual
 pager A script that can take HTML on standard input and 
 display it to the user
--]]----------------------------------------------------------------
local manual = '/usr/share/doc/lua50/manual/manual.html'
local pager = 'lynx -nolist -dump -stdin | less'
-- user editing stops here
----------------------------------------------------------------
-- fast synonyms for library functions
local find = string.find
local gfind = string.gfind
local gsub = string.gsub
local insert = table.insert
-- sections is a list of all sections in the manual
-- each section is referred to by number
local sections = { }
local s = 1 -- number of the current section
-- accumulate the argument as the next section
local function next_section(lines)
 sections[s] = lines
 s = s + 1
 return { }
end
local keytab = { }
 -- For each named thing, stores the number of the section
 -- documenting that thing. The level of indirection allows
 -- us to refer to a section not yet completed, and it makes
 -- it easy to have multiple references to a single section.
local function add_definition(luaval, optional)
 -- add a definition to the current section
 if luaval then
 if keytab[luaval] and keytab[luaval] ~= s then
 if not optional then
 io.stderr:write ("duplicate definitions of " .. luaval .. " in sections " .. s .. " and " .. keytab[luaval] .. '\n')
 end
 else
 keytab[luaval] = s
 end
 end
end
---------- righteous pattern matching for spotting definitions of C things
local rettypes = -- things that can be return types
 { 'void', 'int', 'char', 'const char', 'void', 'size_t',
 'lua_Number', 'lua_CFunction' }
 local isret = { } -- quick set of return types as mapping to bool
 for _, t in pairs(rettypes) do
 isret[t] = true
 end
-- add declaration of a C function
local function add_c_def(line)
 local i, j, rettype, fname =
 find(line, "^%s+(%a[%a ]*%a)%s+%**(lua_[%a_]+)%s*%(lua_State.*%);")
 if not rettype then
 i, j, rettype, fname =
 find(line, "^%s+([%a_]+)%s+%**(lua_[%a_]+)%s*%(lua_State.*%);")
 end
 if rettype and fname and isret[rettype] then
 add_definition(fname)
 end
end
-- add definition of a C macro
local function add_c_macro(line)
 local i, j, mname = find(line, "^%s+#define%s+(lua_[%a_]+)%(")
 add_definition(mname)
end
-- remember definitions by name tags in the HTML
local secnames = { } --- every section
local chapnames = { } --- just h1 and h2 sections
local function add_html_anchor_names(line)
 for n in gfind(line, '<a name="([^"]+)">') do
 n = string.lower(n)
 add_definition(n, 'optional')
 if not find(n, '^[%d%.]+$') then
 table.insert(secnames, n .. '<br>')
 if find(line, "<h[12]>") then
 table.insert(chapnames, n .. '<br>')
 end
 end
 end
end
-- add all known definitions
local function add_definitions(line)
 -- idiom for library functions
 local i, j, luaval, luatab = find(line, "<h3><code>(([%a%._]+)%.[%a%._]+) ")
 add_definition(luaval) -- remember the full name
 add_definition(luatab, 'optional') -- remember the library's name
 add_c_def(line)
 add_c_macro(line)
 add_html_anchor_names(line)
end
 
-- now read in, split, and index all the lines
local lines = { }
for line in io.lines(manual) do
 -- section boundaries are on HTML <h1> and <h2> tags
 line = gsub(line, "&acute;", "'") -- too hard to read
 if find(line, "<h[12]>") then
 lines = next_section(lines)
 end
 insert(lines, line)
 add_definitions(line)
end
lines = next_section(lines) 
-- now add special sections containing HTML anchor names
keytab['sections'] = s
keytab['contents'] = s
next_section(secnames)
keytab['chapters'] = s
next_section(chapnames)
-- here's how we display a section
local function showsection(s)
 local f = assert(io.popen(pager, "w"))
 for i = 1, table.getn(s) do
 f:write(s[i], "\n")
 end
 f:close()
end
-- finally, do something based on the user's input
local h = arg[1]
if not h then
 io.write [[
 try
 lhelp chapters
 lhelp contents
 lhelp <name> -- name from chapters or contents list
 lhelp <cfunction-name> -- e.g., lhelp isnumber
 lhelp <libname> -- e.g., lhelp os
 lhelp <libname>.<funname> -- e.g., lhelp os.time
]]
else
 -- if it helps, put in the lua_ prefix
 if not keytab[h] and keytab['lua_' .. h] then
 h = 'lua_' .. h
 end
 if keytab[h] then -- show a section
 showsection(sections[keytab[h]])
 elseif string.find(h, '^-%d+$') then -- for debugging only (section by number)
 local _, _, n = string.find(h, '^-(%d+)$')
 showsection(sections[tonumber(n)])
 else
 io.write('no help for ', h, '\n')
 end
end

AltStyle によって変換されたページ (->オリジナル) /