gemwriter/gemwriter.lua

248 lines
6.9 KiB
Lua

local conf = require("config")
local tpl = require("template")
local util = require("util")
local writer = {}
writer.app = {
exec_name = "gw",
last_updated = "2022-07-24",
name = "gemwriter",
version = "0.1",
}
writer.conf = {}
writer.defaults = {
atom_file = "atom.xml",
author = "Gem",
-- Atom feed date format
entry_date_format = "%Y-%m-%dT%X+00:00",
entry_ext = ".gmi",
entry_slug = os.date("%Y-%m-%d-%H%M%S"),
entry_file_pattern = "[%/](%d%d%d%d%-%d%d%-%d%d)(.*)[%.](%a*)",
gen_atom_feed = true,
gen_index_page = true,
index_file = "index.gmi",
page_slug = "untitled-" .. os.date("%Y%m%d%H%M%S"),
title = "gemlog",
subtitle = "a Gemini log",
url = "",
output_dir = "log",
rsync_exec = "/usr/bin/rsync",
rsync_options = "-avz",
rsync_remote = "",
}
writer.entries = {}
writer.msg = {
add_entry = "Created ",
help = writer.app.exec_name .. [[ [options] [slug]
Options:
page [slug] Add a new page with the given name
post [slug] Add a new entry with the given name
index Generate an index page and feed of entries
publish Index and copy posts to a remote server (requires rsync)
help Show this help message
version Print version info
]],
index = "Created index page and feed.",
publish = "Published log.",
}
function writer.load_config(config)
for k, v in pairs(writer.defaults) do
if config[k] == nil then
writer.conf[k] = writer.defaults[k]
else
writer.conf[k] = config[k]
end
end
end
function writer.replace_vars(str, vars, vals)
local text = str
for k, v in pairs(vars) do
text = string.gsub(text, v, vals[k])
end
return text
end
function writer.add_entry(slug)
local text = tpl.log_gmi
text = string.gsub(text, tpl.vars.entry.date,
os.date(writer.conf.entry_date_format))
text = string.gsub(text, tpl.vars.entry.author, writer.conf.author)
local entry_name = slug .. writer.conf.entry_ext
os.execute("test -d " .. writer.conf.output_dir .. " || mkdir -p " ..
writer.conf.output_dir)
util.write_file(writer.conf.output_dir .. "/" .. entry_name, text)
end
function writer.get_entries()
local ls_cmd = io.popen("ls " .. writer.conf.output_dir .. " | grep " ..
writer.conf.entry_ext)
local ls = ls_cmd:read("*a")
local entries = {}
local n = 0
local files_list = util.split_str(ls)
for f = 1, #files_list do
if files_list[f] ~= writer.conf.index_file then
n = n + 1
entries[n] = { files_list[f], util.read_file(writer.conf.output_dir ..
"/" .. files_list[f]) }
end
end
return entries
end
function writer.get_entries_meta()
local meta = {}
local entries = writer.get_entries()
for e = 1, #entries do
meta[e] = {}
if string.find(entries[e][2], "# ") == nil then
meta[e]["title"] = entries[e][1]
meta[e]["content"] = entries[e][2]
else
meta[e]["title"] = util.extract_str(entries[e][2], "# ", "\n")
hi1, hi2 = string.find(entries[e][2], "# ")
meta[e]["content"] = string.sub(entries[e][2], hi1,
string.len(entries[e][2]))
end
if string.find(entries[e][2], "author: ") == nil then
meta[e]["author"] = writer.conf.author
else
meta[e]["author"] = util.extract_str(entries[e][2], "author: ", "\n")
end
if string.find(entries[e][2], "date: ") == nil then
meta[e]["date"] = util.extract_file_date(writer.conf.output_dir,
entries[e][1])
if (meta[e]["date"] == "") or (meta[e]["date"] == nil) then
meta[e]["date"] = os.date(writer.conf.entry_date_format)
end
else
meta[e]["date"] = util.extract_str(entries[e][2], "date: ", "\n")
end
if string.find(entries[e][2], "summary: ") == nil then
meta[e]["summary"] = meta[e]["title"]
else
meta[e]["summary"] = util.extract_str(entries[e][2], "summary: ", "\n")
end
if string.find(entries[e][2], "tags: ") == nil then
meta[e]["tags"] = ""
else
meta[e]["tags"] = util.extract_str(entries[e][2], "tags: ", "\n")
end
meta[e]["url"] = writer.conf.url .. "/" .. entries[e][1]
end
return meta
end
function writer.gen_index_page()
local index_text = writer.replace_vars(tpl.index_gmi, tpl.vars.log,
writer.conf)
local entries_text = ""
-- Reverse insert links to log entries, newest first
for e = #writer.entries, 1, -1 do
local entry_date = util.split_str(writer.entries[e]["date"], "(.*)[T]")[1]
-- Get entry filename from the url
local fi1, fi2 = string.find(writer.entries[e]["url"],
writer.conf.entry_file_pattern)
entries_text = entries_text .. "\n=> " ..
string.sub(writer.entries[e]["url"], fi1 + 1, fi2) .. " " ..
entry_date .. " " .. writer.entries[e]["title"]
end
index_text = string.gsub(index_text, tpl.vars.index.entries, entries_text)
util.write_file(writer.conf.output_dir .. "/" .. writer.conf.index_file,
index_text)
end
function writer.gen_atom_feed()
local feed_meta = {
date = os.date(writer.conf.entry_date_format),
url = writer.conf.url .. "/" .. writer.conf.atom_file,
}
local feed_text = writer.replace_vars(tpl.atom_header, tpl.vars.log,
writer.conf)
feed_text = writer.replace_vars(feed_text, tpl.vars.feed, feed_meta)
local feed_entry = ""
-- Reverse insert log entries, newest first
for e = #writer.entries, 1, -1 do
feed_entry = tpl.atom_entry
feed_entry = writer.replace_vars(feed_entry, tpl.vars.entry,
writer.entries[e])
feed_text = feed_text .. feed_entry
end
feed_text = feed_text .. tpl.atom_footer
util.write_file(writer.conf.output_dir .. "/" .. writer.conf.atom_file,
feed_text)
end
function writer.publish()
os.execute(writer.conf.rsync_exec .. " " .. writer.conf.rsync_options ..
" " .. writer.conf.output_dir .. " " .. writer.conf.rsync_remote)
end
local cli = {}
function cli.handle_args(args)
if (args[1] ~= "help") and (args[1] ~= "version") then
writer.load_config(conf)
end
if (args[1] == "index") or (args[1] == "publish") then
writer.entries = writer.get_entries_meta()
if writer.conf.gen_index_page then writer.gen_index_page() end
if writer.conf.gen_atom_feed then writer.gen_atom_feed() end
end
if args[1] == "post" then
local slug = args[2]
if slug == "" then
slug = writer.conf.entry_slug
else
slug = os.date("%Y-%m-%d") .. "-" .. slug
end
writer.add_entry(slug)
print(writer.msg.add_entry .. slug .. writer.conf.entry_ext)
elseif args[1] == "page" then
local slug = args[2]
if slug == "" then slug = writer.conf.page_slug end
writer.add_entry(slug)
print(writer.msg.add_entry .. slug .. writer.conf.entry_ext)
elseif args[1] == "index" then
print(writer.msg.index)
elseif args[1] == "publish" then
writer.publish()
print(writer.msg.publish)
elseif args[1] == "help" then
print(writer.msg.help)
elseif args[1] == "version" then
print(writer.app.name .. " " .. writer.app.version ..
" (" .. writer.app.last_updated .. ")")
end
end
cli.handle_args(arg)