]> git.e2factory.org Git - e2factory.git/commitdiff
Add e2-help, makes it easier to view e2 documentation
authorTobias Ulmer <tu@emlix.com>
Thu, 14 Feb 2013 18:41:14 +0000 (19:41 +0100)
committerTobias Ulmer <tu@emlix.com>
Tue, 26 Feb 2013 18:07:15 +0000 (19:07 +0100)
Signed-off-by: Tobias Ulmer <tu@emlix.com>
local/e2-help.lua [new file with mode: 0644]

diff --git a/local/e2-help.lua b/local/e2-help.lua
new file mode 100644 (file)
index 0000000..f6e6b1b
--- /dev/null
@@ -0,0 +1,285 @@
+--- e2-help command. This tool shows the locally available help
+-- matching the project version.
+--
+-- @module local.e2-help
+
+--[[
+   e2factory, the emlix embedded build system
+
+   Copyright (C) 2013 Tobias Ulmer <tu@emlix.com>, emlix GmbH
+
+   For more information have a look at http://www.e2factory.org
+
+   e2factory is a registered trademark by emlix GmbH.
+
+   This file is part of e2factory, the emlix embedded build system.
+
+   e2factory is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation, either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+]]
+
+local e2lib = require("e2lib")
+local e2tool = require("e2tool")
+local err = require("err")
+local e2option = require("e2option")
+local tools = require("tools")
+
+--- Documentation array, contains doc entries in arbitrary order.
+-- @see doc
+-- @table documentation
+
+--- Doc table describing a specific document.
+-- @field doctype Type of a document (pdf, man, ...), see doctype table
+--                (constant number).
+-- @field section Manpage section (string). Only if the document is a manpage.
+-- @field path Directory path (absolute) to the document (string).
+-- @field filename File name (without path) of the document (string).
+-- @field displayname Name of the document as it should be displayed (string).
+-- @table doc
+
+--- Document type constants.
+local doctype = {
+    PDF = 1, -- PDF document.
+    MAN = 2, -- Man page.
+    TXT = 3, -- Text file.
+}
+
+--- List (print) available man pages in the specified section.
+-- @param documentation Documentation array containing doc tables (table).
+-- @param header Print this string before anything else.
+-- @param section Man page/dir section (string, numbers converted to string).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+local function list_manpage_section(documentation, header, section)
+    section = tostring(section)
+
+    local sorted = {}
+    for _,doc in ipairs(documentation) do
+        if doc.section == section then
+            table.insert(sorted, doc.displayname)
+        end
+    end
+    table.sort(sorted)
+
+    print(header)
+    for _,displayname in ipairs(sorted) do
+            print(string.format("  %s", displayname))
+    end
+    print()
+    return true
+end
+
+--- List (print) all available documentation. Calls subfunctions that know how
+-- to handle various document formats and locations.
+-- @param documentation Documentation array containing doc tables (table).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+local function list_documentation(documentation)
+    local rc, re, e
+
+    local header = "Global and local e2factory tools (section 1):"
+    rc, re = list_manpage_section(documentation, header, 1)
+    if not rc then
+        return false, re
+    end
+
+    header = "e2factory configuration files (section 5):"
+    rc, re = list_manpage_section(documentation, header, 5)
+    if not rc then
+        return false, re
+    end
+
+    return true
+end
+
+--- Discovers and adds local man pages in a specified section relative to
+-- projectdir.
+-- @param documentation Documentation array to be filled
+--                      with doc tables (table).
+-- @param projectdir Path to the root of the project (string).
+-- @param section Man page/dir section (string, numbers converted to string).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+local function discover_manpages(documentation, projectdir, section)
+    local rc, re, e
+    section = tostring(section)
+
+    local mancomp = string.format("man%s", section)
+    local man_re_ext = string.format("%%.%s$", section)
+    local man_re_disp = string.format("^(.+)%%.%s$", section)
+    local mandir = e2lib.join(projectdir, ".e2", "doc", "man", mancomp)
+
+    for f in e2lib.directory(mandir, false, true) do
+        if f:match(man_re_ext) then
+            local doc = {}
+
+            doc.doctype = doctype.MAN
+            doc.section = section
+            doc.path = mandir
+            doc.filename = f
+            doc.displayname = f:match(man_re_disp)
+
+            table.insert(documentation, doc)
+        end
+    end
+
+    return true
+end
+
+--- Discovers documentation in the local project.
+-- @param documentation Documentation array to be filled
+--                      with doc tables (table).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+local function discover_documentation(documentation)
+    local rc, re, e
+
+    e = err.new("while collecting available documentation")
+
+    local projectdir, re = e2lib.locate_project_root()
+    if not projectdir then
+        return false, e:cat(re)
+    end
+
+    rc, re = discover_manpages(documentation, projectdir, 1)
+    if not rc then
+        return false, e:cat(re)
+    end
+
+    rc, re = discover_manpages(documentation, projectdir, 5)
+    if not rc then
+        return false, e:cat(re)
+    end
+
+    return true
+end
+
+--- Display a man page.
+-- @param doc Doc table of the document to be displayed.
+-- @return True on success, false on error.
+-- @return Error object on failure.
+local function display_man_page(doc)
+    local rc, re, e
+    local cmd = {}
+
+    local viewer = tools.get_tool("man")
+    if not viewer then
+        return false, err.new("Manual page viewer is not available")
+    end
+    table.insert(cmd, e2lib.shquote(viewer))
+
+    local viewerflags = tools.get_tool_flags("man")
+    if viewerflags ~= "" then
+        table.insert(cmd, viewerflags)
+    end
+
+    table.insert(cmd, e2lib.shquote(e2lib.join(doc.path, doc.filename)))
+
+    rc = os.execute(table.concat(cmd, ' '))
+    rc = rc / 256
+    if rc ~= 0 then
+        return false, err.new("Manual viewer terminated with exit code %d", rc)
+    end
+
+    return true
+end
+
+--- Find matching document and display it.
+-- @param documentation Documentation array containing doc tables (table).
+-- @param doc_name Document name, supplied by user (string).
+-- @return True on success, false on error.
+-- @return Error object on failure.
+local function display_doc(documentation, doc_name)
+    local rc, re, e
+
+    local doc_re_match = string.format("^%s$", doc_name)
+    local found = 0
+    local founddoc
+    for _,doc in ipairs(documentation) do
+        if doc.displayname:match(doc_re_match) then
+            found = found + 1;
+            founddoc = doc
+        end
+    end
+
+    if found == 0 then
+        return false, err.new("No document matched '%s'", doc_name)
+    elseif found == 1 then
+        if founddoc.doctype == doctype.MAN then
+            display_man_page(founddoc)
+        else
+            e2lib.bomb(string.format("unhandled doctype: %d", founddoc.doctype))
+        end
+    else
+        return false, err.new("More than one document found for '%s',"..
+            " specify a section", doc_name)
+    end
+
+    return true
+end
+
+--- List available help and display them on request. e2-help entry point.
+-- @param arg Global argv table.
+-- @return True on success, false on error.
+-- @return Error object on failure.
+local function e2_help(arg)
+    local rc, re, e
+    e2lib.init()
+
+    local info, re = e2tool.local_init(nil, "help")
+    if not info then
+        return false, re;
+    end
+
+    local opts, arguments = e2option.parse(arg)
+
+    info, re = e2tool.collect_project_info(info, true)
+    if not info then
+        return false, re
+    end
+
+    local documentation = {}
+    if #arguments == 0 then
+        rc, re = discover_documentation(documentation)
+        if not rc then
+            return false, re
+        end
+
+        rc, re = list_documentation(documentation)
+        if not rc then
+            return false, re
+        end
+    elseif #arguments == 1 then
+        rc, re = discover_documentation(documentation)
+        if not rc then
+            return false, re
+        end
+
+        rc, re = display_doc(documentation, arguments[1])
+        if not rc then
+            return false, re
+        end
+    else
+        return false, err.new("Too many arguments")
+    end
+
+    return true
+end
+
+local rc, re = e2_help(arg)
+if not rc then
+    e2lib.abort(re)
+end
+e2lib.finish(0)
+
+-- vim:sw=4:sts=4:et: