summaryrefslogtreecommitdiff
path: root/src/luarocks/cmd/doc.lua
diff options
context:
space:
mode:
authorMike Vink <mike@pionative.com>2025-02-03 21:29:42 +0100
committerMike Vink <mike@pionative.com>2025-02-03 21:29:42 +0100
commit5155816b7b925dec5d5feb1568b1d7ceb00938b9 (patch)
treedeca28ea15e79f6f804c3d90d2ba757881638af5 /src/luarocks/cmd/doc.lua
fetch tarballHEADmaster
Diffstat (limited to 'src/luarocks/cmd/doc.lua')
-rw-r--r--src/luarocks/cmd/doc.lua153
1 files changed, 153 insertions, 0 deletions
diff --git a/src/luarocks/cmd/doc.lua b/src/luarocks/cmd/doc.lua
new file mode 100644
index 0000000..a311700
--- /dev/null
+++ b/src/luarocks/cmd/doc.lua
@@ -0,0 +1,153 @@
+
+--- Module implementing the LuaRocks "doc" command.
+-- Shows documentation for an installed rock.
+local doc = {}
+
+local util = require("luarocks.util")
+local queries = require("luarocks.queries")
+local search = require("luarocks.search")
+local path = require("luarocks.path")
+local dir = require("luarocks.dir")
+local fetch = require("luarocks.fetch")
+local fs = require("luarocks.fs")
+local download = require("luarocks.download")
+
+function doc.add_to_parser(parser)
+ local cmd = parser:command("doc", "Show documentation for an installed rock.\n\n"..
+ "Without any flags, tries to load the documentation using a series of heuristics.\n"..
+ "With flags, return only the desired information.", util.see_also([[
+ For more information about a rock, see the 'show' command.
+]]))
+ :summary("Show documentation for an installed rock.")
+
+ cmd:argument("rock", "Name of the rock.")
+ :action(util.namespaced_name_action)
+ cmd:argument("version", "Version of the rock.")
+ :args("?")
+
+ cmd:flag("--home", "Open the home page of project.")
+ cmd:flag("--list", "List documentation files only.")
+ cmd:flag("--porcelain", "Produce machine-friendly output.")
+end
+
+local function show_homepage(homepage, name, namespace, version)
+ if not homepage then
+ return nil, "No 'homepage' field in rockspec for "..util.format_rock_name(name, namespace, version)
+ end
+ util.printout("Opening "..homepage.." ...")
+ fs.browser(homepage)
+ return true
+end
+
+local function try_to_open_homepage(name, namespace, version)
+ local temp_dir, err = fs.make_temp_dir("doc-"..name.."-"..(version or ""))
+ if not temp_dir then
+ return nil, "Failed creating temporary directory: "..err
+ end
+ util.schedule_function(fs.delete, temp_dir)
+ local ok, err = fs.change_dir(temp_dir)
+ if not ok then return nil, err end
+ local filename, err = download.download("rockspec", name, namespace, version)
+ if not filename then return nil, err end
+ local rockspec, err = fetch.load_local_rockspec(filename)
+ if not rockspec then return nil, err end
+ fs.pop_dir()
+ local descript = rockspec.description or {}
+ return show_homepage(descript.homepage, name, namespace, version)
+end
+
+--- Driver function for "doc" command.
+-- @return boolean: True if succeeded, nil on errors.
+function doc.command(args)
+ local query = queries.new(args.rock, args.namespace, args.version)
+ local iname, iversion, repo = search.pick_installed_rock(query, args.tree)
+ if not iname then
+ local rock = util.format_rock_name(args.rock, args.namespace, args.version)
+ util.printout(rock.." is not installed. Looking for it in the rocks servers...")
+ return try_to_open_homepage(args.rock, args.namespace, args.version)
+ end
+ local name, version = iname, iversion
+
+ local rockspec, err = fetch.load_local_rockspec(path.rockspec_file(name, version, repo))
+ if not rockspec then return nil,err end
+ local descript = rockspec.description or {}
+
+ if args.home then
+ return show_homepage(descript.homepage, name, args.namespace, version)
+ end
+
+ local directory = path.install_dir(name, version, repo)
+
+ local docdir
+ local directories = { "doc", "docs" }
+ for _, d in ipairs(directories) do
+ local dirname = dir.path(directory, d)
+ if fs.is_dir(dirname) then
+ docdir = dirname
+ break
+ end
+ end
+ if not docdir then
+ if descript.homepage and not args.list then
+ util.printout("Local documentation directory not found -- opening "..descript.homepage.." ...")
+ fs.browser(descript.homepage)
+ return true
+ end
+ return nil, "Documentation directory not found for "..name.." "..version
+ end
+
+ docdir = dir.normalize(docdir)
+ local files = fs.find(docdir)
+ local htmlpatt = "%.html?$"
+ local extensions = { htmlpatt, "%.md$", "%.txt$", "%.textile$", "" }
+ local basenames = { "index", "readme", "manual" }
+
+ local porcelain = args.porcelain
+ if #files > 0 then
+ util.title("Documentation files for "..name.." "..version, porcelain)
+ if porcelain then
+ for _, file in ipairs(files) do
+ util.printout(docdir.."/"..file)
+ end
+ else
+ util.printout(docdir.."/")
+ for _, file in ipairs(files) do
+ util.printout("\t"..file)
+ end
+ end
+ end
+
+ if args.list then
+ return true
+ end
+
+ for _, extension in ipairs(extensions) do
+ for _, basename in ipairs(basenames) do
+ local filename = basename..extension
+ local found
+ for _, file in ipairs(files) do
+ if file:lower():match(filename) and ((not found) or #file < #found) then
+ found = file
+ end
+ end
+ if found then
+ local pathname = dir.path(docdir, found)
+ util.printout()
+ util.printout("Opening "..pathname.." ...")
+ util.printout()
+ local ok = fs.browser(pathname)
+ if not ok and not pathname:match(htmlpatt) then
+ local fd = io.open(pathname, "r")
+ util.printout(fd:read("*a"))
+ fd:close()
+ end
+ return true
+ end
+ end
+ end
+
+ return true
+end
+
+
+return doc