+
+
+]]
+
+-- 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)
+
+
+
+
+
+
+
Modules
+ %(nav)
+
+
+
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)
-
-
-
-
-
-
-
Modules
- %(nav)
-
-
-
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)
-
-
-
-
-
-
-
Manual
- %(nav)
-
-
-
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