summaryrefslogtreecommitdiff
path: root/biblio/citation-style-language/citeproc-cli.lua
diff options
context:
space:
mode:
Diffstat (limited to 'biblio/citation-style-language/citeproc-cli.lua')
-rw-r--r--biblio/citation-style-language/citeproc-cli.lua196
1 files changed, 196 insertions, 0 deletions
diff --git a/biblio/citation-style-language/citeproc-cli.lua b/biblio/citation-style-language/citeproc-cli.lua
new file mode 100644
index 0000000000..97a51d724c
--- /dev/null
+++ b/biblio/citation-style-language/citeproc-cli.lua
@@ -0,0 +1,196 @@
+
+--
+-- Copyright (c) 2021-2022 Zeping Lee
+-- Released under the MIT license.
+-- Repository: https://github.com/zepinglee/citeproc-lua
+--
+
+local cli = {}
+
+
+require("lualibs")
+local citeproc = require("citeproc")
+local util = require("citeproc-util")
+local core = require("citeproc-latex-core")
+
+
+local function getopt( arg, options )
+ local tab = {}
+ for k, v in ipairs(arg) do
+ if string.sub( v, 1, 2) == "--" then
+ local x = string.find( v, "=", 1, true )
+ if x then tab[ string.sub( v, 3, x-1 ) ] = string.sub( v, x+1 )
+ else tab[ string.sub( v, 3 ) ] = true
+ end
+ elseif string.sub( v, 1, 1 ) == "-" then
+ local y = 2
+ local l = string.len(v)
+ local jopt
+ while ( y <= l ) do
+ jopt = string.sub( v, y, y )
+ if string.find( options, jopt, 1, true ) then
+ if y < l then
+ tab[ jopt ] = string.sub( v, y+1 )
+ y = l
+ else
+ tab[ jopt ] = arg[ k + 1 ]
+ end
+ else
+ tab[ jopt ] = true
+ end
+ y = y + 1
+ end
+ else
+ if tab.file then
+ error(string.format('Invalid argument "%s"', v))
+ end
+ tab.file = v
+ end
+
+ end
+ return tab
+end
+
+
+local function print_version()
+ io.write(string.format("citeproc-lua %s\n", citeproc.__VERSION__))
+end
+
+
+local function print_help()
+ io.write("Usage: citeproc-lua [options] auxname[.aux]\n")
+ io.write("Options:\n")
+ io.write(" -h, --help Print this message and exit.\n")
+ io.write(" -V, --version Print the version number and exit.\n")
+end
+
+
+local function convert_bib(path, output_path)
+ local contents = util.read_file(path)
+ local bib = citeproc.parse_bib(contents)
+ if not output_path then
+ output_path = string.gsub(path, "%.bib$", ".json")
+ end
+ local file = io.open(output_path, "w")
+ file:write(utilities.json.tojson(bib))
+ file:write('\n')
+ file:close()
+end
+
+
+
+local function read_aux_file(aux_file)
+ local bib_style = nil
+ local bib_files = {}
+ local citations = {}
+ local csl_options = {}
+
+ local file = io.open(aux_file, "r")
+ if not file then
+ error(string.format('Failed to open "%s"', aux_file))
+ return
+ end
+ for line in file:lines() do
+ local match
+ match = string.match(line, "^\\bibstyle%s*(%b{})")
+ if match then
+ bib_style = string.sub(match, 2, -2)
+ else
+ match = string.match(line, "^\\bibdata%s*(%b{})")
+ if match then
+ for _, bib in ipairs(util.split(string.sub(match, 2, -2), "%s*,%s*")) do
+ table.insert(bib_files, bib)
+ end
+ else
+ match = string.match(line, "^\\citation%s*(%b{})")
+ if match then
+ local citation = core.make_citation(string.sub(match, 2, -2))
+ table.insert(citations, citation)
+ else
+ match = string.match(line, "^\\csloptions%s*(%b{})")
+ if match then
+ for key, value in string.gmatch(match, "([%w-]+)=(%w+)") do
+ csl_options[key] = value
+ end
+ end
+ end
+ end
+ end
+ end
+ file:close()
+
+ return bib_style, bib_files, citations, csl_options
+end
+
+
+local function process_aux_file(aux_file)
+ if not util.endswith(aux_file, ".aux") then
+ aux_file = aux_file .. ".aux"
+ end
+
+ local style_name, bib_files, citations, csl_options = read_aux_file(aux_file)
+
+ local lang = csl_options.locale
+
+ local engine = core.init(style_name, bib_files, lang)
+ if csl_options.linking == "true" then
+ engine:enable_linking()
+ end
+ local style_class = engine:get_style_class()
+
+ local citation_strings = core.process_citations(engine, citations)
+
+ local output_string = ""
+
+ for _, citation in ipairs(citations) do
+ local citation_id = citation.citationID
+ if citation_id ~= "@nocite" then
+ local citation_str = citation_strings[citation_id]
+ output_string = output_string .. string.format("\\cslcite{%s}{{%s}{%s}}\n", citation_id, style_class, citation_str)
+ end
+ end
+
+ output_string = output_string .. "\n"
+
+ local result = core.make_bibliography(engine)
+ output_string = output_string .. result
+
+ local output_path = string.gsub(aux_file, "%.aux$", ".bbl")
+ local bbl_file = io.open(output_path, "w")
+ bbl_file:write(output_string)
+ bbl_file:close()
+end
+
+
+function cli.main()
+ local args = getopt(arg, "o")
+
+ -- for k, v in pairs(args) do
+ -- print( k, v )
+ -- end
+
+ if args.V or args.version then
+ print_version()
+ return
+ elseif args.h or args.help then
+ print_help()
+ return
+ end
+
+ if not args.file then
+ error("citeproc: Need exactly one file argument.\n")
+ end
+
+ local path = args.file
+
+ local output_path = args.o or args.output
+ if util.endswith(path, ".bib") then
+ convert_bib(path, output_path)
+ else
+ process_aux_file(path)
+ end
+
+end
+
+
+return cli