
| Current Path : /bin/ |
Linux ift1.ift-informatik.de 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64 |
| Current File : //bin/ctanbib |
#!/usr/bin/env texlua
kpse.set_program_name("luatex")
-- ctanbib -- export ctan entries to bib format
-- Copyright: Michal Hoftich <michal.h21@gmail.com> (2014-2018)
--
-- This work may be distributed and/or modified under the
-- conditions of the LaTeX Project Public License, either version 1.3
-- of this license or (at your option) any later version.
-- The latest version of this license is in
-- http://www.latex-project.org/lppl.txt
-- and version 1.3 or later is part of all distributions of LaTeX
-- version 2005/12/01 or later.
--
-- This work has the LPPL maintenance status `maintained'.
--
-- The Current Maintainer of this work is Michal Hoftich
local bibtype = "manual"
if #arg < 1 or arg[1]=="--help" or arg[1]=="-h" then
print([[ctanbib - convert ctan package information to bibtex format
Usage:
ctanbib [options] <package name>
Available options:
-c,--ctan Use @ctan type instead of @manual
-h,--help Print this message
-v,--version Print version info
]])
os.exit(1)
elseif arg[1]=="--version" or arg[1]=="-v" then
print "ctanbib version 0.1d"
os.exit(1)
elseif arg[1]=="--ctan" or arg[1]=="-c" then
table.remove(arg, 1)
bibtype = "ctan"
end
local pkgname = arg[1]
local url = "https://www.ctan.org/xml/2.0/pkg/" .. pkgname .. "?author-name=true"
local authors_url = "https://ctan.org/xml/2.0/authors"
-- change that for different title scheme
local titleformat = "The %s package"
local bibtexformat = [[
@manual{$package,
title = {$title},
subtitle = {$subtitle},
author = {$author},
url = {$url},
urldate = {$urldate},
date = {$date},
version = {$version}
}
]]
local dom = require('luaxml-domobject')
local load_xml = function(url)
-- local command = io.popen("wget -qO- ".. url,"r")
local command = io.popen("curl -sS ".. url,"r")
local info = command:read("*all")
command:close()
if string.len(info) == 0 then
return false
end
return dom.parse(info)
end
local bibtex_escape = function(a)
local a = a or ""
return a:gsub("([%$%{%}%\\])", function(x)
if x == "\\" then return "\\textbackslash " end
return '\\'..x
end)
end
-- we need to use this method temporarily because of a bug in
-- CTAN API
local author_list
local fetch_author_list = function()
if author_list then return author_list end
local authors = load_xml(authors_url)
author_list = {}
for _, author in ipairs(authors:query_selector("author")) do
-- save all authors under they ID
local id = author:get_attribute("id")
author_list[id] = author
end
return author_list
end
local process_author = function(author)
local current = {}
current[#current+1] = author:get_attribute("familyname")
current[#current+1] = author:get_attribute("givenname")
-- the author is an organization
if #current == 1 then
return "{" .. current[1] .. "}"
elseif #current > 1 then
return table.concat(current, ", ")
end
return nil -- no author
end
-- get the author name and surname
local get_author = function(author)
local name = process_author(author)
if name then return name end
-- if the package XML doesn't contain author name,
-- we need to fetch the authors list from CTAN and find
-- it here
local author_list = fetch_author_list()
local id = author:get_attribute("id")
-- try to find the author id in list of authors
-- if everything fails, just return an empty group
return process_author(author_list[id]) or "{}"
end
local get_authors = function(a)
local retrieved_authors = {}
for _, author in ipairs(a) do
table.insert(retrieved_authors, get_author(author))
end
return table.concat(retrieved_authors," and ")
end
local get_title = function(record)
local title = record:query_selector("name")[1]
if title then
title = title:get_text()
title = title:gsub("^(.)", function(a) return unicode.utf8.upper(a) end)
else
title = pkgname
end
return string.format(titleformat, bibtex_escape(title))
end
local get_url = function(record)
local home = record:query_selector("home")[1]
if home then return home:get_attribute("href") end
return "http://www.ctan.org/pkg/"..pkgname
end
local get_caption = function(record)
local caption = record:query_selector("caption")[1]
if caption then return bibtex_escape(caption:get_text()) end
return nil
end
local get_version = function(record)
local version = record:query_selector("version")[1]
if version then
return version:get_attribute("number"), version:get_attribute("date")
end
end
local ctan_url = function(record)
local ctan = record:query_selector("ctan")[1]
-- some package don't contain the CTAN path
if not ctan then return get_url(record) end
local path = ctan:get_attribute("path")
return path
end
local compile = function(template, records)
return template:gsub("$([a-z]+)", function(a)
return records[a] or ""
end)
end
local record = load_xml(url)
if not record then
print("Cannot find entry for package "..pkgname)
os.exit(1)
end
-- root element is also saved, so we use this trick
-- local record = entry.entry
local e = {}
e.author = get_authors(record:query_selector("authorref"))
e.package = pkgname
e.title = get_title(record)
e.subtitle = get_caption(record)
e.url = get_url(record)
-- use the CTAN path as url for the CTAN type
if bibtype == "ctan" then
e.url = ctan_url(record)
end
e.version, e.date = get_version(record)
e.urldate = os.date("%Y-%m-%d")
local result = compile(bibtexformat, e)
-- update the bibliography type
result = result:gsub("^@manual", "@" .. bibtype)
print(result)