summaryrefslogtreecommitdiff
path: root/src/luarocks/cmd/doc.lua
blob: a311700727fa648935622e6bf6ff4c31f21370cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
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