From: Tobias Ulmer Date: Thu, 14 Feb 2013 18:41:14 +0000 (+0100) Subject: Add e2-help, makes it easier to view e2 documentation X-Git-Tag: e2factory-2.3.13rc1~17 X-Git-Url: https://git.e2factory.org/?a=commitdiff_plain;h=3a08449b37db100450f8093e1098e9381a0f4b59;p=e2factory.git Add e2-help, makes it easier to view e2 documentation Signed-off-by: Tobias Ulmer --- diff --git a/local/e2-help.lua b/local/e2-help.lua new file mode 100644 index 0000000..f6e6b1b --- /dev/null +++ b/local/e2-help.lua @@ -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 , 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 . +]] + +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: