From 3d0058ed9e3df17f31a9e6b939260830ba274bca Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 28 Aug 2019 23:42:31 +0000 Subject: checkcites (29aug19) git-svn-id: svn://tug.org/texlive/trunk@51977 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/support/checkcites/README | 6 +- .../doc/support/checkcites/checkcites-doc.pdf | Bin 218420 -> 289025 bytes .../doc/support/checkcites/checkcites-doc.tex | 22 +- .../texmf-dist/scripts/checkcites/checkcites.lua | 240 +++++++++++++-------- 4 files changed, 171 insertions(+), 97 deletions(-) (limited to 'Master') diff --git a/Master/texmf-dist/doc/support/checkcites/README b/Master/texmf-dist/doc/support/checkcites/README index c2a62c38c10..24ac583f264 100644 --- a/Master/texmf-dist/doc/support/checkcites/README +++ b/Master/texmf-dist/doc/support/checkcites/README @@ -1,10 +1,10 @@ -checkcites.lua -- Version 2.0 from August 25, 2017. -=================================================== +checkcites.lua -- Version 2.1 from July 26, 2019. +================================================= License ------- -Copyright (c) 2012, 2017 Enrico Gregorio, Paulo Roberto Massa Cereda +Copyright (c) 2012, 2019 Enrico Gregorio, Paulo Roberto Massa Cereda - Enrico dot Gregorio at univr dot it - cereda at users dot sf dot net diff --git a/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf index 5f7c5f1212f..3bd33069ae6 100644 Binary files a/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf and b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf differ diff --git a/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex index 5a50af1f1c8..447505587c8 100644 --- a/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex +++ b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex @@ -1,3 +1,7 @@ +% arara: pdflatex +% arara: pdflatex +% arara: pdflatex +% arara: clean: { extensions: [ listing, out, aux, log, toc ] } \documentclass[12pt,a4paper]{article} \usepackage[T1]{fontenc} @@ -16,7 +20,7 @@ \newcommand{\checkcites}{\texttt{checkcites}} \newcommand{\email}[1]{\small\texttt{#1}} -\newcommand{\version}{Version 2.0 from August 25, 2017.} +\newcommand{\version}{Version 2.1 from July 26, 2019.} \newenvironment{infoblock}[1] {\par\addvspace{\medskipamount} @@ -222,8 +226,8 @@ $ checkcites | _| | -_| _| '_| _| | _| -_|_ -| |___|_|_|___|___|_,_|___|_|_| |___|___| -checkcites.lua -- a reference checker script (v2.0) -Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda +checkcites.lua -- a reference checker script (v2.1) +Copyright (c) 2012, 2019, Enrico Gregorio, Paulo Roberto Massa Cereda -------------------------------------------------------------------------- I am sorry, but you have not provided any command line argument, including @@ -258,8 +262,8 @@ $ checkcites --help | _| | -_| _| '_| _| | _| -_|_ -| |___|_|_|___|___|_,_|___|_|_| |___|___| -checkcites.lua -- a reference checker script (v2.0) -Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda +checkcites.lua -- a reference checker script (v2.1) +Copyright (c) 2012, 2019, Enrico Gregorio, Paulo Roberto Massa Cereda Usage: checkcites.lua [ [ --all | --unused | --undefined ] [ --backend ] [ ... ] | --help | --version ] @@ -318,8 +322,8 @@ $ checkcites document.aux | _| | -_| _| '_| _| | _| -_|_ -| |___|_|_|___|___|_,_|___|_|_| |___|___| -checkcites.lua -- a reference checker script (v2.0) -Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda +checkcites.lua -- a reference checker script (v2.1) +Copyright (c) 2012, 2019, Enrico Gregorio, Paulo Roberto Massa Cereda Great, I found 4 citations in 1 file. I also found 1 bibliography file. Let me check this file and extract the references. Please wait a moment. @@ -459,8 +463,8 @@ $ checkcites --backend biber document.bcf | _| | -_| _| '_| _| | _| -_|_ -| |___|_|_|___|___|_,_|___|_|_| |___|___| -checkcites.lua -- a reference checker script (v2.0) -Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda +checkcites.lua -- a reference checker script (v2.1) +Copyright (c) 2012, 2019, Enrico Gregorio, Paulo Roberto Massa Cereda Great, I found 4 citations in 1 file. I also found 1 bibliography file. Let me check this file and extract the references. Please wait a moment. diff --git a/Master/texmf-dist/scripts/checkcites/checkcites.lua b/Master/texmf-dist/scripts/checkcites/checkcites.lua index cdd0df14ef9..c6ff0e396af 100755 --- a/Master/texmf-dist/scripts/checkcites/checkcites.lua +++ b/Master/texmf-dist/scripts/checkcites/checkcites.lua @@ -1,7 +1,7 @@ #!/usr/bin/env texlua -- ----------------------------------------------------------------- -- checkcites.lua --- Copyright 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda +-- Copyright 2012, 2019, Enrico Gregorio, Paulo Roberto Massa Cereda -- -- This work may be distributed and/or modified under the conditions -- of the LaTeX Project Public License, either version 1.3 of this @@ -145,6 +145,19 @@ local function read(file) return lines end +-- Gets a pluralized word based on a counter. +-- @param i Counter. +-- @param a Word in singular. +-- @param b Word in plural. +-- @return Either the first or second word based on the counter. +local function plural(i, a, b) + if i == 1 then + return a + else + return b + end +end + -- Normalizes the string, removing leading and trailing spaces. -- @param str String. -- @return Normalized string without leading and trailing spaces. @@ -167,15 +180,28 @@ local function blacklist(a) return false end +-- Checks if the key is allowed. +-- @param v The key itself. +-- @return Boolean value if the key is allowed. +local function allowed(key) + local keys = { 'string', 'comment' } + for _, v in ipairs(keys) do + if string.lower(key) == v then + return false + end + end + return true +end + -- Extracts the biblographic key. -- @param lines Lines of a file. -- @return Table containing bibliographic keys. local function extract(lines) local result = {} for _, line in ipairs(lines) do - local hit = string.match(line, - '^%s*%@%w+%s*{%s*(.+),') - if hit then + local key, hit = string.match(line, + '^%s*%@(%w+%s*){%s*(.+),') + if key and allowed(key) then if not exists(result, hit) then hit = normalize(hit) table.insert(result, hit) @@ -185,17 +211,48 @@ local function extract(lines) return result end --- Gets a pluralized word based on a counter. --- @param i Counter. --- @param a Word in singular. --- @param b Word in plural. --- @return Either the first or second word based on the counter. -local function plural(i, a, b) - if i == 1 then - return a +-- Adds the extension if the file does not have it. +-- @param file File. +-- @param extension Extension. +-- @return File with proper extension. +local function sanitize(file, extension) + extension = '.' .. extension + if string.sub(file, -#extension) ~= extension then + file = file .. extension + end + return file +end + +-- Checks if a file exists. +-- @param file File. +-- @return Boolean value indicating if the file exists. +local function valid(file) + local handler = io.open(file, 'r') + if handler then + handler:close() + return true else - return b + return false + end +end + +-- Wraps a string based on a line width. +-- @param str String. +-- @param size Line width. +-- @return Wrapped string. +local function wrap(str, size) + local parts = split(str, '[^%s]+') + local r, l = '', '' + for _, v in ipairs(parts) do + if (#l + #v) > size then + r = r .. '\n' .. l + l = v + else + l = normalize(l .. ' ' .. v) + end end + r = normalize(r .. '\n' .. l) + return r end -- Backend namespace @@ -203,11 +260,12 @@ local backends = {} -- Gets data from auxiliary files (BibTeX). -- @param lines Lines of a file. +-- @param rec Recursive switch. -- @return Boolean indicating if an asterisk was found. -- @return Table containing the citations. -- @return Table containing the bibliography files. -backends.bibtex = function(lines) - local citations, bibliography = {}, {} +backends.bibtex = function(lines, rec) + local citations, bibliography, invalid = {}, {}, {} local asterisk, parts, hit = false for _, line in ipairs(lines) do hit = string.match(line, '^%s*\\citation{(.+)}$') @@ -234,18 +292,52 @@ backends.bibtex = function(lines) table.insert(bibliography, v) end end + else + hit = string.match(line, '^%s*\\@input{(.+)}$') + if rec and hit then + hit = sanitize(hit, 'aux') + if not valid(hit) then + table.insert(invalid, hit) + else + local a, b, c = backends.bibtex(read(hit), false) + asterisk = asterisk or a + for _, v in ipairs(b) do + if not exists(citations, v) then + table.insert(citations, v) + end + end + for _, v in ipairs(c) do + if not exists(bibliography, v) then + table.insert(bibliography, v) + end + end + end + end end end end + if #invalid ~= 0 then + print() + print(wrap('Warning: there ' .. plural(#invalid, + 'is an invalid reference ', 'are ' .. + 'invalid references ') .. 'to the ' .. + 'following auxiliary ' .. plural(#invalid, + 'file ', 'files ') .. 'that could not ' .. + 'be resolved at runtime:', 74)) + for _, v in ipairs(invalid) do + print('=> ' .. v) + end + end return asterisk, citations, bibliography end -- Gets data from auxiliary files (Biber). -- @param lines Lines of a file. +-- @param _ To be discarded with biber. -- @return Boolean indicating if an asterisk was found. -- @return Table containing the citations. -- @return Table containing the bibliography files. -backends.biber = function(lines) +backends.biber = function(lines, _) local citations, bibliography = {}, {} local asterisk, parts, hit = false for _, line in ipairs(lines) do @@ -294,28 +386,16 @@ end -- Repeats the provided char a certain number of times. -- @param c Char. --- @param w Number of times. +-- @param size Number of times. -- @return String with a char repeated a certain number of times. -local function pad(c, w) +local function pad(c, size) local r = c - while #r < w do + while #r < size do r = r .. c end return r end --- Adds the extension if the file does not have it. --- @param file File. --- @param extension Extension. --- @return File with proper extension. -local function sanitize(file, extension) - extension = '.' .. extension - if string.sub(file, -#extension) ~= extension then - file = file .. extension - end - return file -end - -- Flattens a table of tables into only one table. -- @param t Table. -- @return Flattened table. @@ -343,23 +423,13 @@ local function apply(c, f) return result end --- Wraps a string based on a line width. --- @param str String. --- @param size Line width. --- @return Wrapped string. -local function wrap(str, size) - local parts = split(str, '[^%s]+') - local r, l = '', '' - for _, v in ipairs(parts) do - if (#l + #v) > size then - r = r .. '\n' .. l - l = v - else - l = normalize(l .. ' ' .. v) - end - end - r = normalize(r .. '\n' .. l) - return r +-- Search the TeX tree for the file. +-- @param library The library reference. +-- @param file The filename. +-- @param extension The extension. +-- @return String pointing to the file location. +local function lookup(library, file, extension) + return library.find_file(file, extension) end -- Prints the script header. @@ -370,8 +440,8 @@ print("| _| | -_| _| '_| _| | _| -_|_ -|") print("|___|_|_|___|___|_,_|___|_|_| |___|___|") print() print(wrap('checkcites.lua -- a reference ' .. - 'checker script (v2.0)', 74)) - print(wrap('Copyright (c) 2012, 2017, ' .. + 'checker script (v2.1)', 74)) + print(wrap('Copyright (c) 2012, 2019, ' .. 'Enrico Gregorio, Paulo ' .. 'Roberto Massa Cereda', 74)) end @@ -446,36 +516,37 @@ operations.all = function(citations, references) end end --- Checks if a file exists. --- @param file File. --- @return Boolean value indicating if the file exists. -local function valid(file) - local handler = io.open(file, 'r') - if handler then - handler:close() - return true - else - return false - end -end - -- Filters a table of files, keeping the inexistent ones. -- @param files Table. +-- @param lib Search library. +-- @param enabled Boolean switch to enable lookup. +-- @param extension Extension for lookup. -- @return Table of inexistent files. -local function validate(files) - local result = {} +-- @return Table of existent files. +local function validate(files, lib, enabled, extension) + local bad, good = {}, {} for _, v in ipairs(files) do if not valid(v) then - table.insert(result, v) + if enabled and lookup(lib, v, extension) then + table.insert(good, lookup(lib, v, extension)) + else + table.insert(bad, v) + end + else + table.insert(good, v) end end - return result + return bad, good end -- Main function. -- @param args Command line arguments. -- @return Integer value indicating the status local function checkcites(args) + + local kpse = require('kpse') + kpse.set_program_name('texlua') + header() local parameters = { @@ -525,8 +596,8 @@ local function checkcites(args) if keys['version'] or keys['help'] then if keys['version'] then print() - print(wrap('checkcites.lua, version 2.0 (dated August ' .. - '25, 2017)', 74)) + print(wrap('checkcites.lua, version 2.1 (dated July ' .. + '26, 2019)', 74)) print(pad('-', 74)) print(wrap('You can find more details about this ' .. @@ -611,16 +682,16 @@ local function checkcites(args) return sanitize(a, (backend == 'bibtex' and 'aux') or 'bcf') end) - local vld = validate(auxiliary) - if #vld ~= 0 then + local invalid, _ = validate(auxiliary, kpse, false, 'aux') + if #invalid ~= 0 then print() print(pad('-', 74)) print(wrap('I am sorry, but I was unable to ' .. - 'locate ' .. plural(#vld, 'this file', + 'locate ' .. plural(#invalid, 'this file', 'these files') .. ' (the extension ' .. 'is automatically set based on the ' .. '"' .. backend .. '" backend):', 74)) - for _, v in ipairs(vld) do + for _, v in ipairs(invalid) do print('=> ' .. v) end @@ -631,13 +702,13 @@ local function checkcites(args) '" to files if not provided.', 74)) print() - print(wrap('Please make sure the ' .. plural(#vld, + print(wrap('Please make sure the ' .. plural(#invalid, 'path is', 'paths are') .. ' ' .. - 'correct and the ' .. plural(#vld, + 'correct and the ' .. plural(#invalid, 'file exists', 'files exist') .. '. ' .. 'There is nothing I can do at the moment. ' .. 'Refer to the user documentation for ' .. - 'details on the file lookup. If ' .. plural(#vld, + 'details on the file lookup. If ' .. plural(#invalid, 'this is not the file', 'these are not the ' .. 'files') .. ' you were expecting, ' .. 'double-check your source file or ' .. @@ -647,7 +718,7 @@ local function checkcites(args) end local lines = flatten(apply(auxiliary, read)) - local asterisk, citations, bibliography = backends[backend](lines) + local asterisk, citations, bibliography = backends[backend](lines, true) print() print(wrap('Great, I found ' .. tostring(#citations) .. ' ' .. @@ -671,27 +742,27 @@ local function checkcites(args) bibliography = apply(bibliography, function(a) return sanitize(a, 'bib') end) - vld = validate(bibliography) - if #vld ~= 0 then + invalid, bibliography = validate(bibliography, kpse, true, 'bib') + if #invalid ~= 0 then print() print(pad('-', 74)) print(wrap('I am sorry, but I was unable to locate ' .. - plural(#vld, 'this file', 'these files') .. ' ' .. + plural(#invalid, 'this file', 'these files') .. ' ' .. '(the extension is automatically set to ' .. '".bib", if not provided):', 74)) - for _, v in ipairs(vld) do + for _, v in ipairs(invalid) do print('=> ' .. v) end print() - print(wrap('Please make sure the ' .. plural(#vld, + print(wrap('Please make sure the ' .. plural(#invalid, 'path is', 'paths are') .. ' ' .. - 'correct and the ' .. plural(#vld, + 'correct and the ' .. plural(#invalid, 'file exists', 'files exist') .. '. ' .. 'There is nothing I can do at the moment. ' .. 'Refer to to the user documentation ' .. 'for details on bibliography lookup. If ' .. - plural(#vld, 'this is not the file', + plural(#invalid, 'this is not the file', 'these are not the files') .. ' you were ' .. 'expecting (wrong bibliography), double-check ' .. 'your source file. The script will end ' .. @@ -718,4 +789,3 @@ end os.exit(checkcites(arg)) -- EOF - -- cgit v1.2.3