Hilbish/nature/commands/doc.lua

193 lines
5.2 KiB
Lua

local ansikit = require 'ansikit'
local commander = require 'commander'
local fs = require 'fs'
local lunacolors = require 'lunacolors'
local Greenhouse = require 'nature.greenhouse'
local Page = require 'nature.greenhouse.page'
local docfuncs = require 'nature.doc'
local function strip(text, ...)
for _, pat in ipairs {...} do
text = text:gsub(pat, '\n')
end
return text
end
local function transformHTMLandMD(text)
return strip(text, '|||', '|%-%-%-%-|%-%-%-%-|')
:gsub('|(.-)|(.-)|', function(entry1, entry2)
return string.format('%s - %s', entry1, entry2)
end)
:gsub('<hr>', '{separator}')
:gsub('<.->', '')
--:gsub('^\n\n', '\n')
:gsub('\n%s+\n', '\n\n')
--:gsub(' \n', '\n\n')
:gsub('{{< (%w+) `(.-)` >}}', function(shortcode, text)
return docfuncs.renderInfoBlock(shortcode, text)
end)
:gsub('```(%w+)\n(.-)```', function(lang, text)
return docfuncs.renderCodeBlock(text)
end)
:gsub('```\n(.-)\n```', function(text)
return docfuncs.renderCodeBlock(text)
end)
:gsub('`[^\n].-`', lunacolors.cyan)
:gsub('#+ (.-\n)', function(heading) return lunacolors.blue(lunacolors.bold('' .. heading)) end)
:gsub('%*%*(.-)%*%*', lunacolors.bold)
end
commander.register('doc', function(args, sinks)
local moddocPath = hilbish.dataDir .. '/docs/'
local stat = pcall(fs.stat, '.git/refs/heads/extended-job-api')
if stat then
-- hilbish git
moddocPath = './docs/'
end
local modules = table.map(fs.readdir(moddocPath), function(f)
return lunacolors.underline(lunacolors.blue(string.gsub(f, '.md', '')))
end)
local doc = [[
Welcome to Hilbish's documentation viewer! Here you can find
documentation for builtin functions and other things related
to Hilbish.
Usage: doc <section> [subdoc]
Available sections: ]] .. table.concat(modules, ', ')
local f
local function handleYamlInfo(d)
local vals = {}
local docs = d
local valsStr = docs:match '^%-%-%-\n.-\n%-%-%-'
if valsStr then
docs = docs:sub(valsStr:len() + 2, #docs)
local pre = docs:sub(1, 1)
if pre == '\n' then
docs = docs:sub(2)
end
-- parse vals
local lines = string.split(valsStr, '\n')
for _, line in ipairs(lines) do
local key = line:match '(%w+): '
local val = line:match '^%w+: (.-)$'
if key then
vals[key] = val
end
end
end
--docs = docs:sub(1, #docs - 1)
return docs, vals
end
if #args > 0 then
local mod = args[1]
f = io.open(moddocPath .. mod .. '.md', 'rb')
local funcdocs = nil
local subdocName = args[2]
if not f then
moddocPath = moddocPath .. mod .. '/'
if not subdocName then
subdocName = '_index'
end
f = io.open(moddocPath .. subdocName .. '.md', 'rb')
local oldmoddocPath = moddocPath
if not f then
moddocPath = moddocPath .. subdocName:match '%w+' .. '/'
f = io.open(moddocPath .. subdocName .. '.md', 'rb')
end
if not f then
moddocPath = oldmoddocPath .. subdocName .. '/'
subdocName = args[3] or '_index'
f = io.open(moddocPath .. subdocName .. '.md', 'rb')
end
if not f then
sinks.out:writeln('No documentation found for ' .. mod .. '.')
return 1
end
end
end
local moddocs = table.filter(fs.readdir(moddocPath), function(f) return f ~= '_index.md' and f ~= 'index.md' end)
local subdocs = table.map(moddocs, function(fname)
return lunacolors.underline(lunacolors.blue(string.gsub(fname, '.md', '')))
end)
local gh = Greenhouse(sinks.out)
function gh:resize()
local size = terminal.size()
self.region = {
width = size.width,
height = size.height - 1
}
end
gh:resize()
function gh:render()
local workingPage = self.pages[self.curPage]
local offset = self.offset
if self.isSpecial then
offset = self.specialOffset
workingPage = self.specialPage
end
local size = terminal.size()
self.sink:write(ansikit.getCSI(size.height - 1 .. ';1', 'H'))
self.sink:write(ansikit.getCSI(0, 'J'))
if not self.isSpecial then
if args[1] == 'api' then
self.sink:writeln(workingPage.title)
self.sink:write(lunacolors.format(string.format('{grayBg} ↳ {white}{italic}%s {reset}', workingPage.description or 'No description.')))
else
self.sink:write(lunacolors.reset(string.format('Viewing doc page %s', moddocPath)))
end
end
end
local backtickOccurence = 0
local function formatDocText(d)
return transformHTMLandMD(d)
--[[
return lunacolors.format(d:gsub('`(.-)`', function(t)
return docfuncs.renderCodeBlock(t)
end):gsub('\n#+.-\n', function(t)
local signature = t:gsub('<.->(.-)</.->', '{underline}%1'):gsub('\\', '<')
return '{bold}{yellow}' .. signature .. '{reset}'
end))
]]--
end
local doc, vals = handleYamlInfo(#args == 0 and doc or formatDocText(f:read '*a'))
if #moddocs ~= 0 and f then
doc = doc .. '\nSubdocs: ' .. table.concat(subdocs, ', ') .. '\n\n'
end
if f then f:close() end
local page = Page(vals.title, doc)
page.description = vals.description
gh:addPage(page)
-- add subdoc pages
for _, sdName in ipairs(moddocs) do
local sdFile = fs.join(sdName, '_index.md')
if sdName:match '.md$' then
sdFile = sdName
end
local f = io.open(moddocPath .. sdFile, 'rb')
local doc, vals = handleYamlInfo(formatDocText(f:read '*a'))
local page = Page(vals.title or sdName, doc)
page.description = vals.description
gh:addPage(page)
end
ansikit.hideCursor()
gh:initUi()
end)