From c4d376b33ef504be226d8090ee59c64bbb963696 Mon Sep 17 00:00:00 2001 From: mitchell <70453897+667e-11@users.noreply.github.com> Date: Wed, 7 Mar 2012 12:47:38 -0500 Subject: Removed `scripts/update_doc` in favor of using `src/Makefile`. --- doc/gen_manual.lua | 66 ++++++++++++ doc/markdowndoc.lua | 223 ++++++++++++++++++++++++++++++++++++++++ modules/lua/adeptsensedoc.lua | 230 ++++++++++++++++++++++++++++++++++++++++++ modules/lua/luadoc.patch | 22 ++++ scripts/adeptsensedoc.lua | 229 ----------------------------------------- scripts/luadoc.patch | 22 ---- scripts/markdowndoc.lua | 221 ---------------------------------------- scripts/update_doc | 108 -------------------- src/Makefile | 19 +++- 9 files changed, 558 insertions(+), 582 deletions(-) create mode 100644 doc/gen_manual.lua create mode 100644 doc/markdowndoc.lua create mode 100644 modules/lua/adeptsensedoc.lua create mode 100644 modules/lua/luadoc.patch delete mode 100644 scripts/adeptsensedoc.lua delete mode 100644 scripts/luadoc.patch delete mode 100644 scripts/markdowndoc.lua delete mode 100755 scripts/update_doc diff --git a/doc/gen_manual.lua b/doc/gen_manual.lua new file mode 100644 index 00000000..5fa06bfe --- /dev/null +++ b/doc/gen_manual.lua @@ -0,0 +1,66 @@ +-- Copyright 2007-2012 Mitchell mitchell.att.foicica.com. See LICENSE. + +local HTML = [[ + + + + %(title) + + + + +
+ +
+

Contents

+ %(toc) +
+
+ %(main) +
+
+ + +]] + +-- Get manual pages. +local pages = {} +local lfs = require 'lfs' +for file in lfs.dir('manual/') do + if file:find('^%d+_.-%.md$') then pages[#pages + 1] = file end +end +table.sort(pages) +pages[#pages + 1] = '../../README.md' +pages[#pages + 1] = '../../CHANGELOG.md' +pages[#pages + 1] = '../../THANKS.md' + +-- Create the navigation list. +local navfile = 'manual/.nav.md' +local f = io.open(navfile, 'wb') +for _, page in ipairs(pages) do + local name = page:match('^%A+(.-)%.md$'):gsub('(%l)(%u)', '%1 %2') + if page:find('^%.%./') then page = page:match('^%A+(.+)$') end + f:write('* [', name, '](', page:gsub('%.md$', '.html'), ')\n') +end +f:close() +local p = io.popen('markdown "'..navfile..'"') +local nav = p:read('*all') +p:close() + +-- Write HTML. +for _, page in ipairs(pages) do + local name = page:match('^%A+(.-)%.md$'):gsub('(%l)(%u)', '%1 %2') + local p = io.popen('markdown -f toc -T "manual/'..page..'"') + local toc, main = p:read('*all'):match('^(.-\n\n)(.+)$') + p:close() + if page:find('^%.%./') then page = page:match('^%A+(.+)$') end + f = io.open('manual/'..page:gsub('%.md$', '.html'), 'wb') + local html = HTML:gsub('%%%(([^)]+)%)', { + title = name..' - Textadept Manual', nav = nav, toc = toc, main = main + }) + f:write(html) + f:close() +end diff --git a/doc/markdowndoc.lua b/doc/markdowndoc.lua new file mode 100644 index 00000000..80918253 --- /dev/null +++ b/doc/markdowndoc.lua @@ -0,0 +1,223 @@ +-- Copyright 2007-2012 Mitchell mitchell.att.foicica.com. See LICENSE. + +local ipairs, type = ipairs, type +local io_open, io_popen = io.open, io.popen +local string_format, string_rep = string.format, string.rep +local table_concat = table.concat + +-- Markdown doclet for Luadoc. +-- Requires Discount (http://www.pell.portland.or.us/~orc/Code/discount/). +-- @usage luadoc -d [output_path] -doclet path/to/markdowndoc [file(s)] +local M = {} + +local NAVFILE = '%s* [%s](%s)\n' +local FUNCTION = '\n### `%s` (%s)\n\n' +--local FUNCTION = '### `%s` (%s)\n\n' +local DESCRIPTION = '> %s\n\n' +local LIST_TITLE = '> %s:\n\n' +local PARAM = '> * `%s`: %s\n' +local USAGE = '> * `%s`\n' +local RETURN = '> * %s\n' +local SEE = '> * [`%s`](#%s)\n' +local TABLE = '\n### `%s`\n\n' +--local TABLE = '### `%s`\n\n' +local FIELD = '> * `%s`: %s\n' +local HTML = [[ + + + + %(title) + + + + +
+ +
+

Contents

+ %(toc) +
+
+ %(main) +
+
+ + +]] + +-- Writes LuaDoc hierarchical module navigation to the given file. +-- @param f The navigation file being written to. +-- @param list The module list. +-- @param parent String parent module with a trailing '.' for sub-modules in +-- order to generate full page links. +local function write_nav(f, list, parent) + if not parent then parent = '' end + local level = 0 + for _ in parent:gmatch('%.') do level = level + 1 end + for _, name in ipairs(list) do + f:write(string_format(NAVFILE, string_rep(' ', level * 4), name, + parent..name..'.html')) + if list[name] then + f:write('\n') + write_nav(f, list[name], parent..name..'.') + end + end +end + +-- Writes a LuaDoc description to the given file. +-- @param f The markdown file being written to. +-- @param description The description. +local function write_description(f, description) + f:write(string_format(DESCRIPTION, description)) +end + +-- Writes a LuaDoc list to the given file. +-- @param f The markdown file being written to. +-- @param title The title of the list. +-- @param fmt The format of a list item. +-- @param list The LuaDoc list. +local function write_list(f, title, fmt, list) + if not list or #list == 0 then return end + if type(list) == 'string' then list = { list } end + f:write(string_format(LIST_TITLE, title)) + for _, value in ipairs(list) do + f:write(string_format(fmt, value, value)) + end + f:write('\n') +end + +-- Writes a LuaDoc hashmap to the given file. +-- @param f The markdown file being written to. +-- @param title The title of the hashmap. +-- @param fmt The format of a hashmap item. +-- @param list The LuaDoc hashmap. +local function write_hashmap(f, title, fmt, hashmap) + if not hashmap or #hashmap == 0 then return end + f:write(string_format(LIST_TITLE, title)) + for _, name in ipairs(hashmap) do + f:write(string_format(fmt, name, hashmap[name] or '')) + end + f:write('\n') +end + +-- Called by LuaDoc to process a doc object. +-- @param doc The LuaDoc doc object. +function M.start(doc) + local modules, files = doc.modules, doc.files + + -- Create the navigation list. + local hierarchy = {} + for _, name in ipairs(modules) do + local parent, self = name:match('^(.-)%.?([^.]+)$') + local h = hierarchy + for table in parent:gmatch('[^.]+') do + if not h[table] then h[table] = {} end + h = h[table] + end + h[#h + 1] = self + end + (require 'lfs').mkdir(M.options.output_dir..'/api') + local navfile = M.options.output_dir..'/api/.nav.md' + local f = io_open(navfile, 'wb') + write_nav(f, hierarchy) + f:close() + local p = io_popen('markdown "'..navfile..'"') + local nav = p:read('*all') + p:close() + + -- Create a map of doc objects to file names so their Markdown doc comments + -- can be extracted. + local filedocs = {} + for _, name in ipairs(files) do filedocs[files[name].doc] = name end + + -- Loop over modules, creating Markdown documents. + for _, name in ipairs(modules) do + local module = modules[name] + local filename = filedocs[module.doc] + + local mdfile = M.options.output_dir..'/api/'..name..'.md' + local f = io_open(mdfile, 'wb') + + -- Write the header and description. + f:write('# ', name, '\n\n') + f:write(module.description, '\n\n') + + -- Extract any Markdown doc comments and insert them. + -- Markdown doc comments must immediately proceed a 'module' declaration + -- (excluding blank lines), start with '-- Markdown:', and end on a blank or + -- uncommented line. + if filename then + local module_declaration, markdown = false, false + local module_file = io_open(filename, 'rb') + for line in module_file:lines() do + if not module_declaration and line:find('^module') then + module_declaration = true + elseif module_declaration and not markdown and line ~= '' then + if line ~= '-- Markdown:' then break end + markdown = true + elseif markdown then + line = line:match('^%-%-%s?(.*)$') + if not line then break end + f:write(line, '\n') + end + end + module_file:close() + end + f:write('\n') + f:write('- - -\n\n') + + -- Write functions. + local funcs = module.functions + if #funcs > 0 then + f:write('## Functions\n\n') + f:write('- - -\n\n') + for _, fname in ipairs(funcs) do + local func = funcs[fname] + f:write(string_format(FUNCTION, func.name, func.name, + table_concat(func.param, ', '):gsub('_', '\\_'))) + write_description(f, func.description) + write_hashmap(f, 'Parameters', PARAM, func.param) + write_list(f, 'Usage', USAGE, func.usage) + write_list(f, 'Return', RETURN, func.ret) + write_list(f, 'See also', SEE, func.see) + f:write('- - -\n\n') + end + f:write('\n') + end + + -- Write tables. + local tables = module.tables + if #tables > 0 then + f:write('## Tables\n\n') + f:write('- - -\n\n') + for _, tname in ipairs(tables) do + local tbl = tables[tname] + f:write(string_format(TABLE, tbl.name, tbl.name)) + write_description(f, tbl.description) + write_hashmap(f, 'Fields', FIELD, tbl.field) + write_list(f, 'Usage', USAGE, tbl.usage) + write_list(f, 'See also', SEE, tbl.see) + f:write('- - -\n\n') + end + end + + f:close() + + -- Write HTML. + local p = io_popen('markdown -f toc -T "'..mdfile..'"') + local toc, main = p:read('*all'):match('^(.-\n\n)(.+)$') + p:close() + toc = toc:gsub('()', '%1%2') -- strip function parameters + f = io_open(M.options.output_dir..'/api/'..name..'.html', 'wb') + local html = HTML:gsub('%%%(([^)]+)%)', { + title = name..' - Textadept API', nav = nav, toc = toc, main = main + }) + f:write(html) + f:close() + end +end + +return M diff --git a/modules/lua/adeptsensedoc.lua b/modules/lua/adeptsensedoc.lua new file mode 100644 index 00000000..89379ea6 --- /dev/null +++ b/modules/lua/adeptsensedoc.lua @@ -0,0 +1,230 @@ +-- Copyright 2007-2012 Mitchell mitchell.att.foicica.com. See LICENSE. + +-- Adeptsense doclet for LuaDoc. +-- This module is used by LuaDoc to create an adeptsense for Lua with a fake +-- ctags file and an api file. +-- To preserve formatting, the included `luadoc.patch` file must be applied to +-- your instance of LuaDoc. It will not affect the look of HTML web pages, only +-- the look of plain-text Adeptsense api files. +-- Since LuaDoc does not recognize module fields, this doclet parses the Lua +-- modules for comments of the form "-- * `field_name`" to generate a field tag +-- and apidoc. Multiple line comments for fields must be indented flush with +-- `field_name` (3 spaces). +-- @usage luadoc -d [output_path] -doclet path/to/adeptsensedoc [file(s)] +local M = {} + +local CTAGS_FMT = '%s\t_\t0;"\t%s\t%s' +local string_format = string.format + +-- Writes a ctag. +-- @param file The file to write to. +-- @param name The name of the tag. +-- @param k The kind of ctag. Lua adeptsense uses 4 kinds: m Module, f Function, +-- t Table, and F Field. +-- @param ext_fields The ext_fields for the ctag. +local function write_tag(file, name, k, ext_fields) + if type(ext_fields) == 'table' then + ext_fields = table.concat(ext_fields, '\t') + end + file[#file + 1] = string_format(CTAGS_FMT, name, k, ext_fields) +end + +-- Writes a function or field apidoc. +-- @param file The file to write to. +-- @param m The LuaDoc module object. +-- @param b The LuaDoc block object. +local function write_apidoc(file, m, b) + -- Function or field name. + local name = b.name + if not name:find('[%.:]') then name = m.name..'.'..name end + -- Block documentation for the function or field. + local doc = {} + -- Function arguments or field type. + local header = name + if b.class == 'function' then + header = header..(b.param and '('..table.concat(b.param, ', ')..')' or '') + end + if b.modifier and b.modifier ~= '' then header = header..' '..b.modifier end + doc[#doc + 1] = header + -- Function or field description. + doc[#doc + 1] = b.description:gsub('\\n', '\\\\n') + -- Function parameters (@param). + if b.class == 'function' and b.param then + for _, p in ipairs(b.param) do + if b.param[p] and #b.param[p] > 0 then + doc[#doc + 1] = '@param '..p..' '..b.param[p]:gsub('\\n', '\\\\n') + end + end + end + -- Function usage (@usage). + if b.class == 'function' and b.usage then + if type(b.usage) == 'string' then + doc[#doc + 1] = '@usage '..b.usage + else + for _, u in ipairs(b.usage) do doc[#doc + 1] = '@usage '..u end + end + end + -- Function returns (@return). + if b.class == 'function' and b.ret then + if type(b.ret) == 'string' then + doc[#doc + 1] = '@return '..b.ret + else + for _, u in ipairs(b.ret) do doc[#doc + 1] = '@return '..u end + end + end + -- See also (@see). + if b.see then + if type(b.see) == 'string' then + doc[#doc + 1] = '@see '..b.see + else + for _, s in ipairs(b.see) do doc[#doc + 1] = '@see '..s end + end + end + -- Format the block documentation. + doc = table.concat(doc, '\n'):gsub('\n', '\\n') + file[#file + 1] = name:match('[^%.:]+$')..' '..doc +end + +-- Called by LuaDoc to process a doc object. +-- @param doc The LuaDoc doc object. +function M.start(doc) +-- require 'luarocks.require' +-- local profiler = require 'profiler' +-- profiler.start() + + local modules = doc.modules + + -- Convert module functions in the Lua luadoc into LuaDoc modules. + local lua_luadoc = doc.files['../modules/lua/lua.luadoc'] + if lua_luadoc then + for _, f in ipairs(lua_luadoc.functions) do + f = lua_luadoc.functions[f] + local module = f.name:match('^([^%.:]+)[%.:]') or '_G' + if not modules[module] then + modules[#modules + 1] = module + modules[module] = { name = module, functions = {} } + -- For functions like file:read(), 'file' is not a module; fake it. + if f.name:find(':') then modules[module].fake = true end + end + local module = modules[module] + module.description = 'Lua '..module.name..' module.' + module.functions[#module.functions + 1] = f.name + module.functions[f.name] = f + end + end + + -- Parse out module fields (-- * `FIELD`: doc) and insert them into the + -- module's LuaDoc. + for _, file in ipairs(doc.files) do + local module_name, field, docs + -- Adds the field to its module's LuaDoc. + local function add_field() + local doc = table.concat(docs, '\n') + doc = doc:gsub('%[([^%]]+)%]%b[]', '%1'):gsub('%[([^%]]+)%]%b()', '%1') + field.description = doc + local m = modules[field.module] + if not m then + local name = field.module + _G.print("Module '"..name.."' does not exist. Faking...") + m = { name = name, functions = {}, fake = true } + modules[#modules + 1] = name + modules[name] = m + end + if not m.fields then m.fields = {} end + m.fields[#m.fields + 1] = field.name + m.fields[field.name] = field + field = nil + end + local f = io.open(file, 'rb') + for line in f:lines() do + if not field and line:find('^module%(') then + -- Get the module's name to add the parsed fields to. + module_name = line:match("^module%('([^']+)'") + elseif line:find('^%-%- %* `') then + -- New field; if another field was parsed right before this one, add + -- the former field to its module's LuaDoc. + if field then add_field() end + field, docs = {}, {} + local name, doc = line:match('^%-%- %* `([^`]+)`([^\r\n]*)') + field.module = name:match('^_G%.(.-)%.[^%.]+$') or module_name or + name:match('^[^%.]+') + field.name = name:match('[^%.]+$') + if doc ~= '' then + field.modifier, doc = doc:match('^%s*([^:]*):?%s*(.*)$') + end + if doc ~= '' then docs[#docs + 1] = doc end + elseif field and line:find('^%-%-%s+[^\r\n]+') then + docs[#docs + 1] = line:match('^%-%-%s%s%s(%s*[^\r\n]+)') + elseif field and + (line:find('^%-%-[\r\n]*$') or line:find('^[\r\n]*$')) then + -- End of field documentation. Add it to its module's LuaDoc. + add_field() + end + end + f:close() + end + + -- Process LuaDoc and write the ctags and api file. + local ctags, apidoc = {}, {} + for _, m in ipairs(modules) do + m = modules[m] + local module = m.name + if not m.fake then + -- Tag the module and write the apidoc. + write_tag(ctags, module, 'm', '') + if module:find('%.') then + -- Tag the last part of the module as a table of the first part. + local parent, child = module:match('^(.-)%.([^%.]+)$') + write_tag(ctags, child, 't', 'class:'..parent) + elseif module ~= '_G' then + -- Tag the module as a global table. + write_tag(ctags, module, 't', '') + end + m.modifier = '[module]' + write_apidoc(apidoc, { name = '_G' }, m) + end + -- Tag the functions and write the apidoc. + for _, f in ipairs(m.functions) do + local func = f:match('[^%.:]+$') + local ext_fields = module == '_G' and '' or 'class:'..module + write_tag(ctags, func, 'f', ext_fields) + write_apidoc(apidoc, m, m.functions[f]) + end + -- Tag the tables and write the apidoc. + for _, t in ipairs(m.tables or {}) do + local table = m.tables[t] + local module = module -- define locally so any modification stays local + if t:find('^_G%.') then module, t = t:match('^_G%.(.-)%.?([^%.]+)$') end + if not module then _G.print(table.name) end + local ext_fields = module == '_G' and '' or 'class:'..module + write_tag(ctags, t, 't', ext_fields) + table.modifier = '[table]' + write_apidoc(apidoc, m, table) + -- Tag the fields of the tables. + t = module..'.'..t + for _, f in ipairs(table.field or {}) do + write_tag(ctags, f, 'F', 'class:'..t) + write_apidoc(apidoc, { name = t }, + { name = f, description = table.field[f] }) + end + end + -- Tag the fields. + for _, f in ipairs(m.fields or {}) do + local ext_fields = module == '_G' and '' or 'class:'..module + write_tag(ctags, f, 'F', ext_fields) + write_apidoc(apidoc, m, m.fields[f]) + end + end + table.sort(ctags) + table.sort(apidoc) + local f = io.open(M.options.output_dir..'/tags', 'w') + f:write(table.concat(ctags, '\n')) + f:close() + f = io.open(M.options.output_dir..'api', 'w') + f:write(table.concat(apidoc, '\n')) + f:close() + +-- profiler.stop() +end + +return M diff --git a/modules/lua/luadoc.patch b/modules/lua/luadoc.patch new file mode 100644 index 00000000..175b5942 --- /dev/null +++ b/modules/lua/luadoc.patch @@ -0,0 +1,22 @@ +--- luadoc/util.lua.orig 2012-02-10 13:34:46.166184400 -0500 ++++ luadoc/util.lua 2012-02-10 13:36:59.847551200 -0500 +@@ -29,8 +29,8 @@ + -- @see string.gsub + + function trim_comment (s) +- s = string.gsub(s, "%-%-+(.*)$", "%1") +- return trim(s) ++ s = string.gsub(s, "%-%-+ ?(.*)$", "%1") ++ return s + end + + ------------------------------------------------------------------------------- +@@ -52,7 +52,7 @@ + if str1 == nil or string.len(str1) == 0 then + return str2 + else +- return str1 .. " " .. str2 ++ return str1 .. "\n" .. str2 + end + end + diff --git a/scripts/adeptsensedoc.lua b/scripts/adeptsensedoc.lua deleted file mode 100644 index e18a4fb4..00000000 --- a/scripts/adeptsensedoc.lua +++ /dev/null @@ -1,229 +0,0 @@ --- Copyright 2007-2012 Mitchell mitchell.att.foicica.com. See LICENSE. - ---- --- Adeptsense doclet for LuaDoc. --- This module is used by LuaDoc to create an adeptsense for Lua with a fake --- ctags file and an api file. --- Since LuaDoc does not recognize module fields, this doclet parses the Lua --- modules for comments of the form "-- * `field_name`" to generate a field tag --- and apidoc. Multiple line comments for fields must be indented flush with --- `field_name` (3 spaces). Indenting more than this preserves formatting in the --- apidoc. --- @usage luadoc -d [output_path] -doclet path/to/adeptsensedoc [file(s)] -module('adeptsensedoc', package.seeall) - -local CTAGS_FMT = '%s\t_\t0;"\t%s\t%s' -local string_format = string.format - --- Writes a ctag. --- @param file The file to write to. --- @param name The name of the tag. --- @param k The kind of ctag. Lua adeptsense uses 4 kinds: m Module, f Function, --- t Table, and F Field. --- @param ext_fields The ext_fields for the ctag. -local function write_tag(file, name, k, ext_fields) - if type(ext_fields) == 'table' then - ext_fields = table.concat(ext_fields, '\t') - end - file[#file + 1] = string_format(CTAGS_FMT, name, k, ext_fields) -end - --- Writes a function or field apidoc. --- @param file The file to write to. --- @param m The LuaDoc module object. --- @param b The LuaDoc block object. -local function write_apidoc(file, m, b) - -- Function or field name. - local name = b.name - if not name:find('[%.:]') then name = m.name..'.'..name end - -- Block documentation for the function or field. - local doc = {} - -- Function arguments or field type. - local header = name - if b.class == 'function' then - header = header..(b.param and '('..table.concat(b.param, ', ')..')' or '') - end - if b.modifier and b.modifier ~= '' then header = header..' '..b.modifier end - doc[#doc + 1] = header - -- Function or field description. - doc[#doc + 1] = b.description:gsub('\\n', '\\\\n') - -- Function parameters (@param). - if b.class == 'function' and b.param then - for _, p in ipairs(b.param) do - if b.param[p] and #b.param[p] > 0 then - doc[#doc + 1] = '@param '..p..' '..b.param[p]:gsub('\\n', '\\\\n') - end - end - end - -- Function usage (@usage). - if b.class == 'function' and b.usage then - if type(b.usage) == 'string' then - doc[#doc + 1] = '@usage '..b.usage - else - for _, u in ipairs(b.usage) do doc[#doc + 1] = '@usage '..u end - end - end - -- Function returns (@return). - if b.class == 'function' and b.ret then - if type(b.ret) == 'string' then - doc[#doc + 1] = '@return '..b.ret - else - for _, u in ipairs(b.ret) do doc[#doc + 1] = '@return '..u end - end - end - -- See also (@see). - if b.see then - if type(b.see) == 'string' then - doc[#doc + 1] = '@see '..b.see - else - for _, s in ipairs(b.see) do doc[#doc + 1] = '@see '..s end - end - end - -- Format the block documentation. - doc = table.concat(doc, '\n'):gsub('\n', '\\n') - file[#file + 1] = name:match('[^%.:]+$')..' '..doc -end - --- Called by LuaDoc to process a doc object. --- @param doc The LuaDoc doc object. -function start(doc) --- require 'luarocks.require' --- local profiler = require 'profiler' --- profiler.start() - - local modules = doc.modules - - -- Convert module functions in the Lua luadoc into LuaDoc modules. - local lua_luadoc = doc.files['../modules/lua/lua.luadoc'] - if lua_luadoc then - for _, f in ipairs(lua_luadoc.functions) do - f = lua_luadoc.functions[f] - local module = f.name:match('^([^%.:]+)[%.:]') or '_G' - if not modules[module] then - modules[#modules + 1] = module - modules[module] = { name = module, functions = {} } - -- For functions like file:read(), 'file' is not a module; fake it. - if f.name:find(':') then modules[module].fake = true end - end - local module = modules[module] - module.description = 'Lua '..module.name..' module.' - module.functions[#module.functions + 1] = f.name - module.functions[f.name] = f - end - end - - -- Parse out module fields (-- * `FIELD`: doc) and insert them into the - -- module's LuaDoc. - for _, file in ipairs(doc.files) do - local module, field, docs - -- Adds the field to its module's LuaDoc. - local function add_field() - local doc = table.concat(docs, '\n') - doc = doc:gsub('%[([^%]]+)%]%b[]', '%1'):gsub('%[([^%]]+)%]%b()', '%1') - field.description = doc - local m = modules[field.module] - if not m then - local name = field.module - _G.print("Module '"..name.."' does not exist. Faking...") - m = { name = name, functions = {}, fake = true } - modules[#modules + 1] = name - modules[name] = m - end - if not m.fields then m.fields = {} end - m.fields[#m.fields + 1] = field.name - m.fields[field.name] = field - field = nil - end - local f = io.open(file, 'rb') - for line in f:lines() do - if not field and line:find('^module%(') then - -- Get the module's name to add the parsed fields to. - module = line:match("^module%('([^']+)'") - elseif line:find('^%-%- %* `') then - -- New field; if another field was parsed right before this one, add - -- the former field to its module's LuaDoc. - if field then add_field() end - field, docs = {}, {} - local name, doc = line:match('^%-%- %* `([^`]+)`([^\r\n]*)') - field.module = name:match('^_G%.(.-)%.[^%.]+$') or module or - name:match('^[^%.]+') - field.name = name:match('[^%.]+$') - if doc ~= '' then - field.modifier, doc = doc:match('^%s*([^:]*):?%s*(.*)$') - end - if doc ~= '' then docs[#docs + 1] = doc end - elseif field and line:find('^%-%-%s+[^\r\n]+') then - docs[#docs + 1] = line:match('^%-%-%s%s%s(%s*[^\r\n]+)') - elseif field and - (line:find('^%-%-[\r\n]*$') or line:find('^[\r\n]*$')) then - -- End of field documentation. Add it to its module's LuaDoc. - add_field() - end - end - f:close() - end - - -- Process LuaDoc and write the ctags and api file. - local ctags, apidoc = {}, {} - for _, m in ipairs(modules) do - m = modules[m] - local module = m.name - if not m.fake then - -- Tag the module and write the apidoc. - write_tag(ctags, module, 'm', '') - if module:find('%.') then - -- Tag the last part of the module as a table of the first part. - local parent, child = module:match('^(.-)%.([^%.]+)$') - write_tag(ctags, child, 't', 'class:'..parent) - elseif module ~= '_G' then - -- Tag the module as a global table. - write_tag(ctags, module, 't', '') - end - m.modifier = '[module]' - write_apidoc(apidoc, { name = '_G' }, m) - end - -- Tag the functions and write the apidoc. - for _, f in ipairs(m.functions) do - local func = f:match('[^%.:]+$') - local ext_fields = module == '_G' and '' or 'class:'..module - write_tag(ctags, func, 'f', ext_fields) - write_apidoc(apidoc, m, m.functions[f]) - end - -- Tag the tables and write the apidoc. - for _, t in ipairs(m.tables or {}) do - local table = m.tables[t] - local module = module -- define locally so any modification stays local - if t:find('^_G%.') then module, t = t:match('^_G%.(.-)%.?([^%.]+)$') end - if not module then _G.print(table.name) end - local ext_fields = module == '_G' and '' or 'class:'..module - write_tag(ctags, t, 't', ext_fields) - table.modifier = '[table]' - write_apidoc(apidoc, m, table) - -- Tag the fields of the tables. - t = module..'.'..t - for _, f in ipairs(table.field or {}) do - write_tag(ctags, f, 'F', 'class:'..t) - write_apidoc(apidoc, { name = t }, - { name = f, description = table.field[f] }) - end - end - -- Tag the fields. - for _, f in ipairs(m.fields or {}) do - local ext_fields = module == '_G' and '' or 'class:'..module - write_tag(ctags, f, 'F', ext_fields) - write_apidoc(apidoc, m, m.fields[f]) - end - end - table.sort(ctags) - table.sort(apidoc) - local f = io.open(options.output_dir..'/tags', 'w') - f:write(table.concat(ctags, '\n')) - f:close() - f = io.open(options.output_dir..'api', 'w') - f:write(table.concat(apidoc, '\n')) - f:close() - --- profiler.stop() -end - -return _M diff --git a/scripts/luadoc.patch b/scripts/luadoc.patch deleted file mode 100644 index 175b5942..00000000 --- a/scripts/luadoc.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- luadoc/util.lua.orig 2012-02-10 13:34:46.166184400 -0500 -+++ luadoc/util.lua 2012-02-10 13:36:59.847551200 -0500 -@@ -29,8 +29,8 @@ - -- @see string.gsub - - function trim_comment (s) -- s = string.gsub(s, "%-%-+(.*)$", "%1") -- return trim(s) -+ s = string.gsub(s, "%-%-+ ?(.*)$", "%1") -+ return s - end - - ------------------------------------------------------------------------------- -@@ -52,7 +52,7 @@ - if str1 == nil or string.len(str1) == 0 then - return str2 - else -- return str1 .. " " .. str2 -+ return str1 .. "\n" .. str2 - end - end - diff --git a/scripts/markdowndoc.lua b/scripts/markdowndoc.lua deleted file mode 100644 index be86b980..00000000 --- a/scripts/markdowndoc.lua +++ /dev/null @@ -1,221 +0,0 @@ --- Copyright 2007-2012 Mitchell mitchell.att.foicica.com. See LICENSE. - -local ipairs, type = ipairs, type -local io_open, io_popen = io.open, io.popen -local string_format, string_rep = string.format, string.rep -local table_concat = table.concat - ---- --- Markdown doclet for Luadoc. --- Requires Discount (http://www.pell.portland.or.us/~orc/Code/discount/). --- @usage luadoc -d [output_path] -doclet path/to/markdowndoc [file(s)] -module('markdowndoc') - -local NAVFILE = '%s* [%s](%s)\n' -local FUNCTION = '
\n### `%s` (%s)\n\n' ---local FUNCTION = '### `%s` (%s)\n\n' -local DESCRIPTION = '> %s\n\n' -local LIST_TITLE = '> %s:\n\n' -local PARAM = '> * `%s`: %s\n' -local USAGE = '> * `%s`\n' -local RETURN = '> * %s\n' -local SEE = '> * [`%s`](#%s)\n' -local TABLE = '\n### `%s`\n\n' ---local TABLE = '### `%s`\n\n' -local FIELD = '> * `%s`: %s\n' -local HTML = [[ - - - - %(title) - - - - -
- -
-
Contents
- %(toc) -
-
- %(main) -
-
- - -]] - --- Writes LuaDoc hierarchical module navigation to the given file. --- @param f The navigation file being written to. --- @param list The module list. --- @param parent String parent module with a trailing '.' for sub-modules in --- order to generate full page links. -local function write_nav(f, list, parent) - if not parent then parent = '' end - local level = 0 - for _ in parent:gmatch('%.') do level = level + 1 end - for _, name in ipairs(list) do - f:write(string_format(NAVFILE, string_rep(' ', level * 4), name, - parent..name..'.html')) - if list[name] then - f:write('\n') - write_nav(f, list[name], parent..name..'.') - end - end -end - --- Writes a LuaDoc description to the given file. --- @param f The markdown file being written to. --- @param description The description. -local function write_description(f, description) - f:write(string_format(DESCRIPTION, description)) -end - --- Writes a LuaDoc list to the given file. --- @param f The markdown file being written to. --- @param title The title of the list. --- @param fmt The format of a list item. --- @param list The LuaDoc list. -local function write_list(f, title, fmt, list) - if not list or #list == 0 then return end - if type(list) == 'string' then list = { list } end - f:write(string_format(LIST_TITLE, title)) - for _, value in ipairs(list) do - f:write(string_format(fmt, value, value)) - end - f:write('\n') -end - --- Writes a LuaDoc hashmap to the given file. --- @param f The markdown file being written to. --- @param title The title of the hashmap. --- @param fmt The format of a hashmap item. --- @param list The LuaDoc hashmap. -local function write_hashmap(f, title, fmt, hashmap) - if not hashmap or #hashmap == 0 then return end - f:write(string_format(LIST_TITLE, title)) - for _, name in ipairs(hashmap) do - f:write(string_format(fmt, name, hashmap[name] or '')) - end - f:write('\n') -end - --- Called by LuaDoc to process a doc object. --- @param doc The LuaDoc doc object. -function start(doc) - local modules, files = doc.modules, doc.files - - -- Create the navigation list. - local hierarchy = {} - for _, name in ipairs(modules) do - local parent, self = name:match('^(.-)%.?([^.]+)$') - local h = hierarchy - for table in parent:gmatch('[^.]+') do - if not h[table] then h[table] = {} end - h = h[table] - end - h[#h + 1] = self - end - local navfile = options.output_dir..'/api/.nav.md' - local f = io_open(navfile, 'wb') - write_nav(f, hierarchy) - f:close() - local p = io_popen('markdown "'..navfile..'"') - local nav = p:read('*all') - p:close() - - -- Create a map of doc objects to file names so their Markdown doc comments - -- can be extracted. - local filedocs = {} - for _, name in ipairs(files) do filedocs[files[name].doc] = name end - - -- Loop over modules, creating Markdown documents. - for _, name in ipairs(modules) do - local module = modules[name] - local filename = filedocs[module.doc] - - local mdfile = options.output_dir..'/api/'..name..'.md' - local f = io_open(mdfile, 'wb') - - -- Write the header and description. - f:write('# ', name, '\n\n') - f:write(module.description, '\n\n') - - -- Extract any Markdown doc comments and insert them. - -- Markdown doc comments must immediately proceed a 'module' declaration - -- (excluding blank lines), start with '-- Markdown:', and end on a blank or - -- uncommented line. - if filename then - local module_declaration, markdown = false, false - local module_file = io_open(filename, 'rb') - for line in module_file:lines() do - if not module_declaration and line:find('^module') then - module_declaration = true - elseif module_declaration and not markdown and line ~= '' then - if line ~= '-- Markdown:' then break end - markdown = true - elseif markdown then - line = line:match('^%-%-%s?(.*)$') - if not line then break end - f:write(line, '\n') - end - end - module_file:close() - end - f:write('\n') - f:write('- - -\n\n') - - -- Write functions. - local funcs = module.functions - if #funcs > 0 then - f:write('## Functions\n\n') - f:write('- - -\n\n') - for _, fname in ipairs(funcs) do - local func = funcs[fname] - f:write(string_format(FUNCTION, func.name, func.name, - table_concat(func.param, ', '):gsub('_', '\\_'))) - write_description(f, func.description) - write_hashmap(f, 'Parameters', PARAM, func.param) - write_list(f, 'Usage', USAGE, func.usage) - write_list(f, 'Return', RETURN, func.ret) - write_list(f, 'See also', SEE, func.see) - f:write('- - -\n\n') - end - f:write('\n') - end - - -- Write tables. - local tables = module.tables - if #tables > 0 then - f:write('## Tables\n\n') - f:write('- - -\n\n') - for _, tname in ipairs(tables) do - local tbl = tables[tname] - f:write(string_format(TABLE, tbl.name, tbl.name)) - write_description(f, tbl.description) - write_hashmap(f, 'Fields', FIELD, tbl.field) - write_list(f, 'Usage', USAGE, tbl.usage) - write_list(f, 'See also', SEE, tbl.see) - f:write('- - -\n\n') - end - end - - f:close() - - -- Write HTML. - local p = io_popen('markdown -f toc -T "'..mdfile..'"') - local toc, main = p:read('*all'):match('^(.-\n\n)(.+)$') - p:close() - toc = toc:gsub('()', '%1%2') -- strip function parameters - f = io_open(options.output_dir..'/api/'..name..'.html', 'wb') - local html = HTML:gsub('%%%(([^)]+)%)', { - title = name..' - Textadept API', nav = nav, toc = toc, main = main - }) - f:write(html) - f:close() - end -end diff --git a/scripts/update_doc b/scripts/update_doc deleted file mode 100755 index ee824678..00000000 --- a/scripts/update_doc +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/lua --- Copyright 2007-2012 Mitchell mitchell.att.foicica.com. See LICENSE. - -local all = false -if #arg == 0 then all = true end - -local luadoc = all -local manual = all -local doxygen = all -local adeptsense = all - -for _, doctype in ipairs(arg) do - if doctype == 'luadoc' then - luadoc = true - elseif doctype == 'manual' then - manual = true - elseif doctype == 'doxygen' then - doxygen = true - elseif doctype == 'adeptsense' then - adeptsense = true - end -end - --- Generate LuaDoc. -if luadoc then - os.execute('rm -r ../doc/api/*') - os.execute('luadoc -d ../doc -doclet markdowndoc '.. - '../modules ../core ../lexers/lexer.lua') -end - --- Generate the Manual. -if manual then - local HTML = [[ - - - - %(title) - - - - -
- -
-
Contents
- %(toc) -
-
- %(main) -
-
- - - ]] - - -- Get manual pages. - local pages = {} - local lfs = require 'lfs' - for file in lfs.dir('../doc/manual/') do - if file:find('^%d+_.-%.md$') then pages[#pages + 1] = file end - end - table.sort(pages) - pages[#pages + 1] = '../../README.md' - pages[#pages + 1] = '../../CHANGELOG.md' - pages[#pages + 1] = '../../THANKS.md' - - -- Create the navigation list. - local navfile = '../doc/manual/.nav.md' - local f = io.open(navfile, 'wb') - for _, page in ipairs(pages) do - local name = page:match('^%A+(.-)%.md$'):gsub('(%l)(%u)', '%1 %2') - if page:find('^%.%./') then page = page:match('^%A+(.+)$') end - f:write('* [', name, '](', page:gsub('%.md$', '.html'), ')\n') - end - f:close() - local p = io.popen('markdown "'..navfile..'"') - local nav = p:read('*all') - p:close() - - -- Write HTML. - for _, page in ipairs(pages) do - local name = page:match('^%A+(.-)%.md$'):gsub('(%l)(%u)', '%1 %2') - local p = io.popen('markdown -f toc -T "../doc/manual/'..page..'"') - local toc, main = p:read('*all'):match('^(.-\n\n)(.+)$') - p:close() - if page:find('^%.%./') then page = page:match('^%A+(.+)$') end - f = io.open('../doc/manual/'..page:gsub('%.md$', '.html'), 'wb') - local html = HTML:gsub('%%%(([^)]+)%)', { - title = name..' - Textadept Manual', nav = nav, toc = toc, main = main - }) - f:write(html) - f:close() - end -end - --- Generate Doxygen documentation. -if doxygen then - os.execute('cd ../; doxygen Doxyfile') -end - --- Create Lua adeptsense for textadept. -if adeptsense then - os.execute('luadoc -d ../modules/lua -doclet adeptsensedoc '.. - '../modules ../core ../lexers/lexer.lua') -end diff --git a/src/Makefile b/src/Makefile index d9b3f4f5..99d70744 100644 --- a/src/Makefile +++ b/src/Makefile @@ -22,6 +22,7 @@ WINDRES = LDL = -ldl LUAJIT_LIB = libluajit.a LUAJIT_MAKE = +LUADOC = luadoc # Win32 (WIN32=1) ifdef WIN32 @@ -40,6 +41,7 @@ WINDRES = i486-mingw32-windres LDL = LUAJIT_LIB = lua51.dll LUAJIT_MAKE = HOST_CC="gcc -m32" CROSS=i486-mingw32- TARGET_SYS=Windows +LUADOC = luadoc_start.bat endif # Mac OSX (OSX=1) @@ -61,6 +63,7 @@ WINDRES = LDL = LUAJIT_LIB = libluajit.a LUAJIT_MAKE = +LUADOC = luadoc endif # No debugging unless DEBUG=1. @@ -177,6 +180,19 @@ clean: rm -f ../$(TEXTADEPT) *.o *.a *.dll cd luajit && make clean +doc: manual luadoc adeptsense doxygen +manual: + cd ../doc && lua gen_manual.lua +luadoc: ../modules ../core ../lexers/lexer.lua + cd ../doc && $(LUADOC) -d . -doclet markdowndoc $^ +adeptsense: ../modules ../core ../lexers/lexer.lua + cd ../modules && $(LUADOC) -d lua --doclet lua/adeptsensedoc $^ +doxygen: Doxyfile + cd ../ && doxygen $< +cleandoc: + rm -f ../doc/manual/*.html + rm -rf ../doc/api ../doc/doxygen + # Package (only for Linux x86_64) # Pass 'VERSION=[release version]' to 'make'. @@ -205,8 +221,7 @@ MODULESDIR = $(RELEASEDIR32)/modules MODULESPKG = ../releases/$(RELEASEDIR32).modules.zip release: ../$(TEXTADEPT) ../$(TEXTADEPT32) ../$(TEXTADEPTWIN32) \ - ../$(TEXTADEPTMAC) ../$(TEXTADEPTLPNG12) - sh -c 'cd ../scripts && ./update_doc' + ../$(TEXTADEPTMAC) ../$(TEXTADEPTLPNG12) doc hg archive $(RELEASEDIR32) rm $(RELEASEDIR32)/.hg* cp -r ../doc $(RELEASEDIR32) -- cgit v1.2.3