Murga-Projects Forums
murgaLua to html - Printable Version

+- Murga-Projects Forums (http://www.murga-projects.com/forum)
+-- Forum: Project Forums (/forumdisplay.php?fid=1)
+--- Forum: MurgaLua - General (/forumdisplay.php?fid=2)
+--- Thread: murgaLua to html (/showthread.php?tid=302)


murgaLua to html - mikshaw - 03-09-2008 05:42 AM

I started this conversion script this morning, which I hope to use to convert murgaLua scripts into syntax highlighted html.
For now it's really sloppy, and there are several things that will need to be worked out:
multiline comments, ignoring keywords within comments and strings, nested strings, multiline strings,
and of course doing it line-by-line rather than reading the whole file with every command.

I'm done working on it for now, though, so I'll post in case anyone has any suggestions, or just wants to play with it.

Code:
DELETED


I found a Perl script that converts lua proper to html, and I was thinking of modifying that for CGI use to convert online lua files on the fly,
but if I get this working well, maybe I'll use it with CGILua or haserl.


RE: murgaLua to html - iGame3D - 03-09-2008 06:52 AM

Awesome man. Weird color scheme but thats totally modifiable.
Would be great to build an interface for this so we can choose a color scheme.

I don't know how you mastered those search strings...all that %stuff confuses me.

Reminds of the first time I import an EPS into Pagemaker as text...I printed it out..oops 16 pages of crazy Postscript...I had dreams of being able to script images in Illustrator back in 93.


RE: murgaLua to html - mikshaw - 03-09-2008 07:56 AM

The color scheme is based on the scheme I use in Vim, which is limited to 8 colors and is essentially the Vim lua syntax file + some additions for FLTK.
If I ever finsh this it will of course be made to allow the user to simply fill in a set of color name variables with whatever value they want.

I was having a terrible time trying to figure out how to do any of the things mentioned above, which is why I left it.
I'll probably need to study some other scripts to see how they do pattern modification.
As this is mainly just a series of gsub commands, it may need almost a total rewrite just to make it more efficient.
I was looking at the markdown.lua script a little while ago, and was amazed at how complicated that script was just to do some minor text formatting (and without even using syntax highlighting).
As far as I can tell, that's overkill when you can simply wrap the whole thing in a pre tag and just concentrate on changing colors.

In any case, this project definitely seems less complex that doing syntax in a text editor....there's no concern about matching exact words in most cases.
Still, I see a LOT of stuff that needs tweaking.

Quote:
I don't know how you mastered those search strings...all that %stuff confuses me.

I definitely haven't mastered it. I almost always need to have the Lua "string manipulation" section open for reference.
Some of those % are probably not necessary...I use them to escape just about any non-alphanumeric character in string.* patterns just so I don't have to remember which ones are necessary to escape =o)
And I'm constantly referring to the Lua manual to remember when to use * or - or +
Also, there is an unnecessary use of ([^%w]) in there. It technically should be (*%W), since I'm not searching for a set.


RE: murgaLua to html - mikshaw - 03-09-2008 08:31 AM

Found something that was already written for this task. I just need to tweak it for murgaLua:
http://lua-users.org/lists/lua-l/2001-08/msg00108.html

EDIT: I ca't say that I like this any better than what I have now, as far as the results.
After fixing the old Lua syntax to work with current, it still merely works for specific keywords. What I was working with is less specific,
because it doesn't need to be that specific when you are translating a script that is assumed to be proper Lua.
All you need, for example with string.*, is to find string followed by a dot followed by an alphanumeric string, rather than a full specific string.

So I'm planning to try to combimne the two scripts into one that is general like the one I have but is less redundant like the one Philippe wrote.


RE: murgaLua to html - mikshaw - 03-10-2008 05:44 AM

Made a few improvements to it this morning.
It's still sloppy, but the results are better than before.
I'm hoping it will eventually create w3c compliant HTML, but that will be a last step. First I need to deal with setting the output filename dynamically (just haven't bothered to fix that yet) and try to work out nested/multiline stuff.

Code:
filename="/home/dsl/widgets_demo/widgets.lua"
rc="#FFFF00" -- color for reserved words
pc="#00FFFF" -- "name.function" functions
fc="#00FFFF" -- lua functions
sc="#FF0000" -- strings
nc="#FF0000" -- numbers
mc="#00FF00" -- methods
wc="#FF00FF" -- FLTK classes
ec="#FF0000" -- FLTK constants
cc="#0000FF" -- comments

reserved={ "and","break","do","else","elseif","end","false","for","function","if","in",
           "local","nil","not","or","repeat","return","then","true","until","while" }
package={ "copas","coroutine","debug","fltk","gzip","io","lfs","lzo","math","md5","mime",
          "murgaLua","os","package","random","socket","sqlite3","string","table","zlib" }
funk={ "_G","_VERSION","assert","collectgarbage","dofile","error","getfenv","getmetatable",
       "ipairs","load","loadfile","loadstring","module","next","pairs","pcall","print",
       "rawequal","rawget","rawset","require","select","setfenv","setmetatable","tonumber",
       "tostring","type","unpack","xpcall" }

function parse_table(tab,color,pre,post)
for i=1,table.getn(tab) do
  mystring=string.gsub(mystring,pre..tab[i]..post,"%1<font color="..color..">%2</font>%3")
end
end

input=io.open(filename)
if input then
input:close()
print("<html><head><title>"..filename.."</title></head><body bgcolor=black text=white><pre>")
for line in io.lines(filename) do
mystring=" "..line.." " -- spaces allow %W to work with beginning/end of string
mystring=string.gsub(mystring,"%&","&amp;")
mystring=string.gsub(mystring,"%<","&lt;")
mystring=string.gsub(mystring,"%>","&gt;")
mystring=string.gsub(mystring,"(%D*)(%d+)(%D)","%1<font color="..nc..">%2</font>%3") -- digits (do this before any colors are defined)
mystring=string.gsub(mystring,'(".-")',"<font color="..sc..">%1</font>") -- quotes
mystring=string.gsub(mystring,"(%:%l.-)(%()","<font color="..mc..">%1</font>%2") -- methods
parse_table(reserved,rc,"(%W)(",")(%W)")
parse_table(package,pc,"(%W)(","%.[%w_]*)(%W)")
parse_table(funk,fc,"([^:%w])(",")(%W)")
mystring=string.gsub(mystring,"(%W)(fltk%:Fl[_%w]*)(%W)","%1<font color="..wc..">%2</font>%3") -- fltk:Fl_*
mystring=string.gsub(mystring,"(%W)(fltk%.FL[_%u]*)(%W)","%1<font color="..ec..">%2</font>%3") -- fltk constants

-- wipe out formatting from "--" comments
commentstart,n=string.find(mystring,"%-%-")
if commentstart then
  if commentstart == 1 then
    mystring=string.gsub(mystring,"%<.-%>","")
    mystring="<font color="..cc..">"..mystring.."</font>"
  else
    firststring=string.sub(mystring,1,commentstart-1)
    secondstring=string.sub(mystring,commentstart,string.len(mystring))
    secondstring=string.gsub(secondstring,"%<.-%>","")
    mystring=firststring.."<font color="..cc..">"..secondstring.."</font>"
  end
end

print(mystring)
end
--end
print("</pre></body></html>")
end




RE: murgaLua to html - mikshaw - 03-12-2008 04:59 AM

I overlooked a link on the page where I'd found the Perl script. This link points to a lua script that works much better, much faster, than what I had been working on
http://lua-users.org/wiki/LuaToHtml

I'm modifying it to work specifically with murgaLua scripts, but not finished with that yet. So far I've removed the parts that deal with Lua 4 and have added most of the functions available through the Lua modules and FLTK included with murgaLua 0.6.4. I want to split the Fl_Widget entries into a separate table, though, so they will have unique color, and need to go through the standard functions to make sure they include everything found in murgaLua.

EDIT: The original author had a large table containing all of the functions available in Lua 5. This would be a ridiculous way to add all of the FLTK functions and extra modules, so I'm building tables dynamically using parts of existing murgaLua tables. This cuts down development time drastically, although I still have some thinking to do about how to include the methods of all the different widgets without adding too much bulk to the code.
I'll post the results when I get that sorted...some time in the next couple of days I suspect, assuming I'm going to be interested in working on it again before then.


RE: murgaLua to html - mikshaw - 03-13-2008 03:47 AM

Here's an example of what I have so far. It seems to be pretty close to fully-functional for murgaLua scripts, but I need to run some more tests.

It took 13.7 seconds to convert the widgets demo script directory to html (1.8ghz cpu) . That's not ideal, but much better than I had accomplished with my own script.

I don't think it needs the html function anymore, but I haven't tried without it yet.

EDIT: I guess html cannot be uploaded, so I'll just post the script....

Code:
------------------------------------------------------------------------------
--  Lua 2 HTML (MODIFIED)
--  Original author Peter Shook <http://lua-users.org/wiki/PeterShook>

-- Modified by mikshaw for use specific to MurgaLua
-- http://www.murga-projects.com/murgaLua/
-- and to generate "valid HTML"
-- mik's changes:
--    Removed Lua 4.0 code
--    Added FLTK and modules included with murgaLua
--    Replaced much of the long attr table with a loop
--    Uses CSS for highlighting (currently an embedded style)
--
-- usage: murgaLua murga2html.lua myscript.lua > myscript.html
------------------------------------------------------------------------------

local Pkg = { Name = 'Lua2HTML' }

local special_chars = {
  ['&'] = '&amp;',
  ['"'] = '&quot;',
  ['<'] = '&lt;',
  ['>'] = '&gt;',
}

local special
function special(x) return special_chars[x] end

local quote
function quote(str)
  return(string.gsub(str, '([&"<>])', special))
end

local colour
function colour(color)
  local quote = quote
  local b = '<span class="'.. color ..'">'
  local e = '</span>'
  return function(x) return b .. quote(x) .. e end
end

local html
function html(t, f)
  local b = '<'.. t ..'>'
  local e = '</'.. t ..'>'
  return function(x) return b .. f(x) .. e end
end

-- Font display is now handled by css
-- see the bottom of the script  - mikshaw
local operator = colour'oper'
local note     = colour'note'
local ctrl     = colour'ctrl'
local std      = colour'std'
local literal  = colour'lit'
local acomment = colour'com'
local fl       = colour'fl'
local cnst     = colour'cnst'

local keywords_attr = {
  ['nil']       = literal,
  ['true']      = literal,
  ['false']     = literal,
  ['NULL']     = literal,

  ['local']     = note,
  ['function']  = ctrl,
  ['return']    = note,
  ['break']     = note,

  ['not']       = ctrl,
  ['and']       = ctrl,
  ['or']        = ctrl,

  ['if']        = ctrl,
  ['then']      = ctrl,
  ['else']      = ctrl,
  ['elseif']    = ctrl,

  ['for']       = ctrl,
  ['in']        = ctrl,
  ['while']     = ctrl,
  ['do']        = ctrl,
  ['end']       = ctrl,
  ['repeat']    = ctrl,
  ['until']     = ctrl,
}

local other_attr = {
  ['%']   = note,
  ['=']   = note,
  ['{']   = ctrl,
  ['}']   = ctrl,
  ['+']   = operator,
  ['-']   = operator,
  ['*']   = operator,
  ['/']   = operator,
  ['^']   = operator,
  ['<']   = operator,
  ['<=']  = operator,
  ['>']   = operator,
  ['>=']  = operator,
  ['==']  = operator,
  ['~=']  = operator,
  ['..']  = operator,
}

local stdfunctions_attr = {
  arg = std, self = std,
  _G = std, _LOADED = std, _REQUIREDNAME = std, _TRACEBACK = std, _VERSION = std,
  add = std, assert = std, bind_lua_addtovtable = std, collectgarbage = std,
  dofile = std, error = std, gcinfo = std, getMenu = std, getUserData = std,
  getfenv = std, getmetatable = std, ipairs = std, load = std, loadfile = std,
  loadlib = std, loadstring = std, module = std, newproxy = std, next = std,
  pairs = std, pcall = std, print = std, rawequal = std, rawget = std, rawset = std,
  require = std, select = std, setMenu = std, setfenv = std, setmetatable = std,
  tonumber = std, tostring = std, type = std, unpack = std, xpcall = std,
  __index = std, __newindex = std, __gc = std, __eq = std, __add = std, __sub = std,
  __mul = std, __div = std, __unm = std, __pow = std, __lt = std, __le = std,
  __concat = std, __call = std, __tostring = std, __metatable = std, __fenv = std,
  coroutine=std, debug=std, io=std, math=std, os=std, package=std, string=std, table=std,
  copas=std, gzip=std, lfs=std, lzo=std, md5=std, mime=std, murgaLua=std, random=std, socket=std, sqlite3=std, zlib=std,
}

-- This is a LOT easier than typing out tables, and will be
-- dynamically updated with future changes to these modules
local fltk_attr={ fltk = fl, Fl = fl } -- FLTK functions
local fltkcnst_attr = { }      -- FLTK constants
local fltkmeth_attr = { }      -- FLTK methods
local murga_attr = { ['murgaLua_About'] = cnst, ['murgaLua_ExePath'] = cnst, ['murgaLua_Version'] = cnst }
local ml_mods={ copas, coroutine, debug, gzip, io, lfs, lzo, math, md5,
mime, murgaLua, os, package, random, socket, sqlite3, string, table, zlib }

for i,t in pairs(ml_mods) do
--  stdfunctions_attr[t] = std -- can't figure out how to add this
  for k,v in pairs(t) do
    if type(v)=="function" then stdfunctions_attr[k] = std end
  end
end

for k,v in pairs(fltk) do
if type(v)=="function" then fltk_attr[k] = fl
elseif type(v)=="number" then fltkcnst_attr[k] = cnst end
end

for k,v in pairs(_G) do
  if type(v)=="table" and string.find(k,"^Fl") then
   for a,b in pairs(v) do
     if type(b)=="function" then stdfunctions_attr[a] = std end
    end
  end
end

local sqstring
function sqstring(code, e)
  while 1 do
    e = string.find(code, '[\'\\]', e)
    if not e then error'bad single quoted string' end
    if string.find(code, '^\\.', e) then
      e = e+2
    elseif string.find(code, '^\'', e) then
      return e
    else
      error'impossible?'
    end
  end
end

local dqstring
function dqstring(code, e)
  while 1 do
    e = string.find(code, '[\"\\]', e)
    if not e then error'bad double quoted string' end
    if string.find(code, '^\\.', e) then
      e = e+2
    elseif string.find(code, '^\"', e) then
      return e
    else
      error'impossible?'
    end
  end
end

local longstring
function longstring(code, e)
  local count = 0
  local b
  while 1 do
    b,e = string.find(code, '[%[%]].', e)
    if not b then error'bad long comment or string' end
    if string.find(code, '^%[%[', b) then
      e = e+1
      count = count+1
    elseif string.find(code, '^%]%]', b) then
      if count == 0 then
        return e
      end
      e = e+1
      count = count-1
    else
      -- okay
    end
  end
end

local other
function other(code, i)
  local b,e
  b,e = string.find(code, '^\'.', i)
  if b then return sqstring(code, e), literal end

  b,e = string.find(code, '^\".', i)
  if b then return dqstring(code, e), literal end

  b,e = string.find(code, '^%[%[.', i)
  if b then return longstring(code, e), literal end

  b,e = string.find(code, '^%.%.%.', i) if b then return e end
  b,e = string.find(code, '^%.%.', i)   if b then return e end
  b,e = string.find(code, '^%=%=', i)   if b then return e end
  b,e = string.find(code, '^%~%=', i)   if b then return e end
  b,e = string.find(code, '^%>%=', i)   if b then return e end
  b,e = string.find(code, '^%<%=', i)   if b then return e end

  return i
end

local number
function number(code, i)
  local b,e,e1,e2,e3
  b,e1 = string.find(code, '^%d+%.%d*', i)  -- D+ . D*
  b,e2 = string.find(code, '^%d*%.%d+', i)  -- D* . D+
  b,e3 = string.find(code, '^%d+', i)       -- D+
  i = e1 or e2 or e3
  b,e = string.find(code, '^[Ee][+-]?%d+', i+1)
  return e or i, literal
end

local word
function word(code, i)
  local b,e
  b,e = string.find(code, '^[_%a][_%w]*', i)
  local token = string.sub(code, b, e)
  return e, fltk_attr[token] or fltkcnst_attr[token] or keywords_attr[token] or stdfunctions_attr[token] or murga_attr[token]
end

local comment
function comment(code, i)
  local b,e
  b,e = string.find(code, '^%-%-%[%[.', i)
  if b then return longstring(code, e) end

  b,e = string.find(code, '^%-%-[^\n]*', i)
  if b then return e end

  b,e = string.find(code, '^%#[^\n]*', i)
  if b then return e end
end

local highlight
function highlight(code, outfnc)
  code = string.gsub(code, '\r\n', '\n')  -- DOS is a pain

  local line = { number = 0 }
  local ln
  function ln()
    line.number = line.number+1
    return string.format('\n<span class=\"com\">%4d</span>  ', line.number)
    --return string.format('\n%4d  ', line.number)
  end
  local output
  function output(x, fmt)
    fmt = fmt or function(x) return x end
    x = string.gsub(x, '(%S[^\n]*)', fmt)  -- format groups of non-newline characters
    x = string.gsub(x, '\n', ln)           -- add line number after a newline
    outfnc(x)
  end

  output'\n'  -- line number 1

  local ws = 1
  local tok, e, fmt
  while 1 do
    e = ws
    while 1 do
      tok = string.find(code, '%S', e)
      if not tok then return end
      if not string.find(code, '^[-#]', tok) then break end
      e = comment(code, tok)
      if not e then break end
      e = e+1
    end

    output(string.sub(code, ws, tok-1), acomment) -- white space and comments

    if     string.find(code, '^[_%a]', tok) then e,fmt = word  (code, tok)
    elseif string.find(code, '^%.?%d', tok) then e,fmt = number(code, tok)
    elseif string.find(code, '^%p', tok)    then e,fmt = other (code, tok)
    else
      error'impossible?'
    end

    local token = string.sub(code, tok, e)
    output(token, fmt or other_attr[token])

    ws = e+1
  end
end

function Pkg.lua2html(filename, outfnc)
  local fh = io.open(filename, "r")
  local code =  fh:read('*a')
  io.close(fh)

-- There are 16 color names accepted by w3c HTML/CSS validator
-- aqua, black, blue, fuchsia, gray, green, lime, maroon,
-- navy, olive, purple, red, silver, teal, white, yellow
  outfnc = outfnc or io.write
  outfnc([[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<style type="text/css">
span.oper { color: red; font-weight: bold }
span.note { color: purple; font-weight: bold }
span.ctrl { color: navy; font-weight: bold }
span.std  { color: teal }
span.lit  { color: blue }
span.com  { color: silver }
span.fl   { color: olive }
span.cnst { color: green }
</style>
<title>]]..filename..[[</title>
</head>
<body>]])
  outfnc("<h3>".. filename .."</h3>\n")
  outfnc'<pre>'
  highlight(code, outfnc)
  outfnc'</pre>\n</body></html>'
end

Pkg.lua2html(arg[1])

return Pkg




RE: murgaLua to html - iGame3D - 03-13-2008 10:10 AM

Very nice.
I find gray a better color for comments than silver, which is a bit too close to invisible.

How to disable the line numbers?
Its a nice feature but death to copy and paste of scripts.

Found it at line #275

Code:
-x = string.gsub(x, '\n', ln)           -- add line number after a newline



MurgaLua...now with eye candy. :-)


RE: murgaLua to html - mikshaw - 03-13-2008 10:34 AM

There is a slightly newer version of the script that uses an external css file rather than having the colors defined in the script. It allows you to tweak the colors of all your pages without having to regenerate them, and lets me not give a care whether or not someone uses invalid color names because the html itself will still be valid. Also you'll be able to style the line numbers separate from comments.

You got me thinking about possibly adding a simpler way to toggle the use of line numbers....a variable would probably be simplest to script, but a commandline switch would probably be simplest for the end user.
But that's for later. I'm just going to test this next version a bit more then I have to get back to the demo project.


RE: murgaLua to html - mikshaw - 03-13-2008 12:01 PM

Ok, that was easier than I thought. You can now pass the script a "-n" parameter in order to skip the line numbers, or edit the "uselinenumbers" variable to make it default. There are a couple other variables near the top of the file that can be used to change the CSS filename and the HTML character set.

Code:
#!/home/dsl/bin/murgaLua-0.6.4
------------------------------------------------------------------------------
--  Lua 2 HTML (MODIFIED)
--  Original author Peter Shook <http://lua-users.org/wiki/PeterShook>

-- Modified by mikshaw for use specific to MurgaLua
-- http://www.murga-projects.com/murgaLua/
-- and to generate valid 4.01 strict HTML
-- mik's changes:
--    Removed Lua 4.0 code
--    Added FLTK and modules included with murgaLua
--    Replaced much of the long attr table with loops
--    Added code to generate proper HTML 4
--    Uses external CSS file for highlighting (default is Murga.css)
--    Commandline option to skip line numbers
--
-- usage: murgaLua murga2html.lua [-n] myscript.lua > myscript.html
--        use -n to skip writing line numbers
------------------------------------------------------------------------------

local Pkg = { Name = 'Lua2HTML' }

-- a file path relative to the html file
-- See example css file at the bottom
local cssfile='Murga.css'
-- change this to 0 if you don't want to bother with the -n option
local dolinenumber=1
-- not sure what affect on html validation might come from changing this
local charset='ISO-8859-1'

local inputFile
if arg[1] == "-n" then
  inputFile=arg[2]
  dolinenumber=0
else
  inputFile=arg[1]
end

local special_chars = {
  ['&'] = '&amp;',
  ['"'] = '&quot;',
  ['<'] = '&lt;',
  ['>'] = '&gt;',
}

local special
function special(x) return special_chars[x] end

local quote
function quote(str)
  return(string.gsub(str, '([&"<>])', special))
end

local colour
function colour(class)
  local quote = quote
  local b = '<span class="'.. class ..'">'
  local e = '</span>'
  return function(x) return b .. quote(x) .. e end
end

-- CSS classes: <span class="oper">keyword</span>
local operator = colour'oper'
local note     = colour'note'
local ctrl     = colour'ctrl'
local std      = colour'std'
local literal  = colour'lit'
local acomment = colour'com'
local fl       = colour'fl'
local cnst     = colour'cnst'

local keywords_attr = {
  ['nil']       = literal,
  ['true']      = literal,
  ['false']     = literal,
  ['NULL']     = literal,

  ['local']     = note,
  ['function']  = ctrl,
  ['return']    = note,
  ['break']     = note,

  ['not']       = ctrl,
  ['and']       = ctrl,
  ['or']        = ctrl,

  ['if']        = ctrl,
  ['then']      = ctrl,
  ['else']      = ctrl,
  ['elseif']    = ctrl,

  ['for']       = ctrl,
  ['in']        = ctrl,
  ['while']     = ctrl,
  ['do']        = ctrl,
  ['end']       = ctrl,
  ['repeat']    = ctrl,
  ['until']     = ctrl,
}

local other_attr = {
  ['%']   = note,
  ['=']   = note,
  ['{']   = ctrl,
  ['}']   = ctrl,
  ['+']   = operator,
  ['-']   = operator,
  ['*']   = operator,
  ['/']   = operator,
  ['^']   = operator,
  ['<']   = operator,
  ['<=']  = operator,
  ['>']   = operator,
  ['>=']  = operator,
  ['==']  = operator,
  ['~=']  = operator,
  ['..']  = operator,
}

local stdfunctions_attr = {
  arg = std, self = std,
  _G = std, _LOADED = std, _REQUIREDNAME = std, _TRACEBACK = std, _VERSION = std,
  add = std, assert = std, bind_lua_addtovtable = std, collectgarbage = std,
  dofile = std, error = std, gcinfo = std, getMenu = std, getUserData = std,
  getfenv = std, getmetatable = std, ipairs = std, load = std, loadfile = std,
  loadlib = std, loadstring = std, module = std, newproxy = std, next = std,
  pairs = std, pcall = std, print = std, rawequal = std, rawget = std, rawset = std,
  require = std, select = std, setMenu = std, setfenv = std, setmetatable = std,
  tonumber = std, tostring = std, type = std, unpack = std, xpcall = std,
  __index = std, __newindex = std, __gc = std, __eq = std, __add = std, __sub = std,
  __mul = std, __div = std, __unm = std, __pow = std, __lt = std, __le = std,
  __concat = std, __call = std, __tostring = std, __metatable = std, __fenv = std,
  coroutine=std, debug=std, io=std, math=std, os=std, package=std, string=std, table=std,
  copas=std, gzip=std, lfs=std, lzo=std, md5=std, mime=std, murgaLua=std, random=std, socket=std, sqlite3=std, zlib=std,
}

-- This is a LOT easier than typing out tables, and will be
-- dynamically updated with future changes to these modules
local fltk_attr={ fltk = fl, Fl = fl } -- FLTK functions
local fltkcnst_attr = { }      -- FLTK constants
local fltkmeth_attr = { }      -- FLTK methods
local murga_attr = { ['murgaLua_About'] = cnst, ['murgaLua_ExePath'] = cnst, ['murgaLua_Version'] = cnst }
local ml_mods={ copas, coroutine, debug, gzip, io, lfs, lzo, math, md5,
mime, murgaLua, os, package, random, socket, sqlite3, string, table, zlib }

for i,t in pairs(ml_mods) do
--  stdfunctions_attr[t] = std -- can't figure out how to add this
  for k,v in pairs(t) do
    if type(v)=="function" then stdfunctions_attr[k] = std end
  end
end

for k,v in pairs(fltk) do
if type(v)=="function" then fltk_attr[k] = fl
elseif type(v)=="number" then fltkcnst_attr[k] = cnst end
end

for k,v in pairs(_G) do
  if type(v)=="table" and string.find(k,"^Fl") then
   for a,b in pairs(v) do
     if type(b)=="function" then stdfunctions_attr[a] = std end
    end
  end
end

local sqstring
function sqstring(code, e)
  while 1 do
    e = string.find(code, '[\'\\]', e)
    if not e then error'bad single quoted string' end
    if string.find(code, '^\\.', e) then
      e = e+2
    elseif string.find(code, '^\'', e) then
      return e
    else
      error'impossible?'
    end
  end
end

local dqstring
function dqstring(code, e)
  while 1 do
    e = string.find(code, '[\"\\]', e)
    if not e then error'bad double quoted string' end
    if string.find(code, '^\\.', e) then
      e = e+2
    elseif string.find(code, '^\"', e) then
      return e
    else
      error'impossible?'
    end
  end
end

local longstring
function longstring(code, e)
  local count = 0
  local b
  while 1 do
    b,e = string.find(code, '[%[%]].', e)
    if not b then error'bad long comment or string' end
    if string.find(code, '^%[%[', b) then
      e = e+1
      count = count+1
    elseif string.find(code, '^%]%]', b) then
      if count == 0 then
        return e
      end
      e = e+1
      count = count-1
    else
      -- okay
    end
  end
end

local other
function other(code, i)
  local b,e
  b,e = string.find(code, '^\'.', i)
  if b then return sqstring(code, e), literal end

  b,e = string.find(code, '^\".', i)
  if b then return dqstring(code, e), literal end

  b,e = string.find(code, '^%[%[.', i)
  if b then return longstring(code, e), literal end

  b,e = string.find(code, '^%.%.%.', i) if b then return e end
  b,e = string.find(code, '^%.%.', i)   if b then return e end
  b,e = string.find(code, '^%=%=', i)   if b then return e end
  b,e = string.find(code, '^%~%=', i)   if b then return e end
  b,e = string.find(code, '^%>%=', i)   if b then return e end
  b,e = string.find(code, '^%<%=', i)   if b then return e end

  return i
end

local number
function number(code, i)
  local b,e,e1,e2,e3
  b,e1 = string.find(code, '^%d+%.%d*', i)  -- D+ . D*
  b,e2 = string.find(code, '^%d*%.%d+', i)  -- D* . D+
  b,e3 = string.find(code, '^%d+', i)       -- D+
  i = e1 or e2 or e3
  b,e = string.find(code, '^[Ee][+-]?%d+', i+1)
  return e or i, literal
end

local word
function word(code, i)
  local b,e
  b,e = string.find(code, '^[_%a][_%w]*', i)
  local token = string.sub(code, b, e)
  return e, fltk_attr[token] or fltkcnst_attr[token] or keywords_attr[token] or stdfunctions_attr[token] or murga_attr[token]
end

local comment
function comment(code, i)
  local b,e
  b,e = string.find(code, '^%-%-%[%[.', i)
  if b then return longstring(code, e) end

  b,e = string.find(code, '^%-%-[^\n]*', i)
  if b then return e end

  b,e = string.find(code, '^%#[^\n]*', i)
  if b then return e end
end

local highlight
function highlight(code, outfnc)
  code = string.gsub(code, '\r\n', '\n')  -- DOS is a pain

  local line = { number = 0 }
  local ln
  function ln()
    line.number = line.number+1
    return string.format('\n<span class=\"lnum\">%4d</span>  ', line.number)
    --return string.format('\n%4d  ', line.number)
  end
  local output
  function output(x, fmt)
    fmt = fmt or function(x) return x end
    x = string.gsub(x, '(%S[^\n]*)', fmt)  -- format groups of non-newline characters
    if dolinenumber==1 then x = string.gsub(x, '\n', ln)  end         -- add line number after a newline
    outfnc(x)
  end

  output'\n'  -- line number 1

  local ws = 1
  local tok, e, fmt
  while 1 do
    e = ws
    while 1 do
      tok = string.find(code, '%S', e)
      if not tok then return end
      if not string.find(code, '^[-#]', tok) then break end
      e = comment(code, tok)
      if not e then break end
      e = e+1
    end

    output(string.sub(code, ws, tok-1), acomment) -- white space and comments

    if     string.find(code, '^[_%a]', tok) then e,fmt = word  (code, tok)
    elseif string.find(code, '^%.?%d', tok) then e,fmt = number(code, tok)
    elseif string.find(code, '^%p', tok)    then e,fmt = other (code, tok)
    else
      error'impossible?'
    end

    local token = string.sub(code, tok, e)
    output(token, fmt or other_attr[token])

    ws = e+1
  end
end

function Pkg.lua2html(filename, outfnc)
  local fh = io.open(filename, "r")
  local code =  fh:read('*a')
  io.close(fh)

  outfnc = outfnc or io.write
  outfnc([[<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=]]..charset..[[">
<link href="]]..cssfile..[[" rel="stylesheet" type="text/css" title="default">
<title>]]..filename..[[</title>
</head>
<body>]])
  outfnc("<h3>".. filename .."</h3>\n")
  outfnc'<pre>\n'
  highlight(code, outfnc)
  outfnc'</pre>\n</body></html>'
end

--[[

/* Example CSS file */
/*
There are 16 color names accepted by w3c HTML/CSS validator
  aqua, black, blue, fuchsia, gray, green, lime, maroon,
  navy, olive, purple, red, silver, teal, white, yellow
Otherwise you should use RGB or HEX values
*/

span.oper { color: #FF0000; font-weight: bold } /* mathematical/comparison operators */
span.note { color: #CC0033; font-weight: bold } /* controls */
span.ctrl { color: #993333; font-weight: bold } /* controls */
span.std  { color: #009900 } /* Lua functions */
span.lit  { color: #6666CC } /* strings/numbers */
span.com  { color: #999999 } /* comments */
span.lnum { color: #999999 } /* line numbers */
span.fl   { color: #CC6633 } /* FLTK functions/methods */
span.cnst { color: #990033 } /* FLTK constants */

]]
-- I don't know why the above comment gets dropped if it's at the very end of the script

Pkg.lua2html(inputFile)
return Pkg