summaryrefslogtreecommitdiff
path: root/Master
diff options
context:
space:
mode:
Diffstat (limited to 'Master')
-rw-r--r--Master/texmf-dist/doc/support/checkcites/README88
-rw-r--r--Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdfbin219274 -> 218420 bytes
-rw-r--r--Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex400
-rwxr-xr-xMaster/texmf-dist/scripts/checkcites/checkcites.lua1275
4 files changed, 1007 insertions, 756 deletions
diff --git a/Master/texmf-dist/doc/support/checkcites/README b/Master/texmf-dist/doc/support/checkcites/README
index 461a08370fc..c2a62c38c10 100644
--- a/Master/texmf-dist/doc/support/checkcites/README
+++ b/Master/texmf-dist/doc/support/checkcites/README
@@ -1,10 +1,10 @@
-checkcites.lua -- Version 1.0i from December 18, 2012.
-======================================================
+checkcites.lua -- Version 2.0 from August 25, 2017.
+===================================================
License
-------
-Copyright 2012 Enrico Gregorio, Paulo Roberto Massa Cereda
+Copyright (c) 2012, 2017 Enrico Gregorio, Paulo Roberto Massa Cereda
- Enrico dot Gregorio at univr dot it
- cereda at users dot sf dot net
@@ -17,18 +17,18 @@ About
-----
checkcites is a Lua script written for the sole purpose of detecting
-unused or undefined references from both LaTeX auxiliary or
-bibliography files. We use 'unused reference' to refer to the
-reference present the bibliography file -- with the '.bib'
-extension -- but not cited in the '.tex' file. The 'undefined
-reference' is exactly the opposite, that is, the items cited in the
-'.tex' file, but not present in the '.bib' file.
-
-The original idea came from a question posted in the TeX.sx community
-about how to check which bibliography entries were not used. We
-decided to write a script to check references. We opted for Lua,
-since it's a very straightforward language and it has an interpreter
-available on every modern TeX distribution.
+unused or undefined references from both LaTeX auxiliary or bibliography
+files. We use the term *unused reference* to refer to the reference
+present the bibliography file -- with the '.bib' extension -- but not
+cited in the '.tex' file. The term *undefined reference* is exactly the
+opposite, i.e, the item cited in the '.tex' file, but not present in the
+'.bib' file.
+
+The original idea came from a question posted in the TEX community at
+Stack Exchange about how to check which bibliography entries were not
+used. We decided to write a script to check references. We opted for
+Lua, since it's a very straightforward language and it has an
+interpreter available on every modern TEX distribution.
Installation
------------
@@ -62,14 +62,50 @@ Usage
-----
The script is pretty simple to use. The only requirement is a recent
-TeX distribution, such as TeX Live. Then run checkcites:
+TeX distribution, such as TeX Live.
+
+checkcites uses the generated auxiliary files to start the analysis.
+From version 2.0 on, the scripts supports two backends:
+
+-> bibtex
+
+Default behavior, the script checks '.aux' files looking for citations,
+in the form of '\citation{a}'. For every \citation line found, checkcites
+will extract the citations and add them to a table, even for multiple
+citations separated by commas, like '\citation{a,b,c}'. The citation
+table contains no duplicate values. At the same time checkcites also
+looks for bibliography data, in the form of '\bibdata{a}'. Similarly,
+for every '\bibdata' line found, the script will extract the bibliography
+data and add them to a table, even if they are separated by commas, like
+'\bibdata{d,e,f}'. Again, no duplicate values are allowed. Stick with this
+backend if you are using BibTeX or BibLaTeX with the 'backend=bibtex'
+package option.
+
+-> biber
+
+With this backend, the script checks '.bcf files' (which are XML-based)
+looking for citations, in the form of 'bcf:citekey' tags. For every tag
+found, checkcites will extract the corresponding values and add them to
+a table. The citation table contains no duplicate values. At the same
+time checkcites also looks for bibliography data, in the form of
+'bcf:datasource' tags. Similarly, for every tag found, the script will
+extract the bibliography data and add them to a table. Again, no duplicate
+values are allowed. Stick with this backend if you are using BibLaTeX with
+the default options or with the 'backend=biber' option explicitly set.
+
+Open a terminal and run checkcites:
$ checkcites
-It will print the script usage. The only required argument is the
-'.aux' file which is generated when you compile your '.tex' file.
-If your main document is named 'foo.tex', you will have a 'foo.aux'
-file too. To run the script on that file, go with:
+When you run checkcites without providing any argument to it, the a message
+error will appear. Do not panic! Try again with the --help flag:
+
+$ checkcites --help
+
+If you are using BibTeX, simply provide the auxiliary file -- the one with
+the '.aux' extension -- which is generated when you compile your main '.tex'
+file. For example, if your main document is named 'foo.tex', you probably
+have a 'foo.aux' file too. Then simply invoke
$ checkcites foo.aux
@@ -95,6 +131,18 @@ $ checkcites --all foo.aux
If no special argument is provided, --all is set as default.
+If you are using BibLaTeX, we need to inspect '.bcf' files instead. For
+example, if your main document is named 'foo.tex', you probably have a
+'foo.bcf' file too. Then invoke
+
+$ checkcites foo.aux --backend biber
+
+Note the --backend flag used for BibLaTeX support. We can even omit the
+file extension, the script will automatically assign one based on the
+current backend.
+
+That is it, folks!
+
Official code repository
------------------------
diff --git a/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf
index 61c412726da..5f7c5f1212f 100644
--- a/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf
+++ b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf
Binary files differ
diff --git a/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex
index afc5e2629f0..5a50af1f1c8 100644
--- a/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex
+++ b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex
@@ -4,6 +4,7 @@
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
+\usepackage{tgpagella}
\usepackage[margin=1in]{geometry}
@@ -15,7 +16,7 @@
\newcommand{\checkcites}{\texttt{checkcites}}
\newcommand{\email}[1]{\small\texttt{#1}}
-\newcommand{\version}{Version 1.0i from December 18, 2012.}
+\newcommand{\version}{Version 2.0 from August 25, 2017.}
\newenvironment{infoblock}[1]
{\par\addvspace{\medskipamount}
@@ -43,25 +44,25 @@
\section{Introduction}
\label{sec:intro}
-\checkcites\ is a Lua script written for the sole purpose of detecting
-unused or undefined references from both \LaTeX{} auxiliary or
-bibliography files. We use \emph{unused reference} to refer to the
-reference present the bibliography file --~with the \verb|.bib|
-extension~-- but not cited in the \verb|.tex| file. The
-\emph{undefined reference} is exactly the opposite, that is, the items
-cited in the \texttt{.tex} file, but not present in the \verb|.bib|
-file.
-
-The original idea came from a question posted in the
-\href{http://tex.stackexchange.com}{TeX.sx community} about
-\href{http://tex.stackexchange.com/questions/43276}{how to check which
-bibliography entries were not used}. We decided to write a script to
-check references. We opted for Lua, since it's a very straightforward
-language and it has an interpreter available on every modern \TeX\
-distribution.
+\checkcites\ is a Lua script written for the sole purpose of
+detecting unused or undefined references from both \LaTeX\ auxiliary
+or bibliography files. We use the term \emph{unused reference} to
+refer to the reference present the bibliography file~--~with the
+\verb|.bib| extension~--~but not cited in the \verb|.tex| file.
+The term \emph{undefined reference} is exactly the opposite, i.e,
+the item cited in the \verb|.tex| file, but not present in the
+\verb|.bib| file.
+
+The original idea came from a question posted
+in the \TeX\ community at Stack Exchange about
+\href{http://tex.stackexchange.com/questions/43276}{how to check
+which bibliography entries were not used}. We decided to write a
+script to check references. We opted for Lua, since it is a very
+straightforward language and it has an interpreter available on every
+modern \TeX\ distribution.
\begin{infoblock}{Attention!}
-\checkcites\ is known to run with the most recent \verb|texlua| and
+\checkcites\ is known to run with the most recent \verb|texlua| and
\verb|lua| interpreters. Unfortunately, the code is incompatible with
interpreters prior to the Lua 5.1 language specification.
\end{infoblock}
@@ -69,68 +70,79 @@ interpreters prior to the Lua 5.1 language specification.
\section{How the script works}
\label{sec:howto}
-\checkcites\ uses the generated \verb|.aux| file to start the
-analysis. The first step is to extract all citations found, in the
-form of \verb|\citation{a}|. For every \verb|\citation| line found,
-\checkcites\ will extract the citations and add them to a table, even
-for multiple citations separated by commas, like
-\verb|\citation{a,b,c}|. Then the citations table has all duplicate
-values removed --~in other words, the table becomes a set. Let's call
-$A$ the set of citations.
+\checkcites\ uses the generated auxiliary files to start the
+analysis. From version 2.0 on, the scripts supports two backends:
+
+\begin{description}
+\item[\texttt{bibtex}] Default behavior, the script checks
+\verb|.aux| files looking for citations, in the form of
+\verb|\citation{a}|. For every \verb|\citation| line found,
+\checkcites\ will extract the citations and add them to a
+table, even for multiple citations separated by commas, like
+\verb|\citation{a,b,c}|. The citation table contains no duplicate
+values. At the same time \checkcites\ also looks for bibliography
+data, in the form of \verb|\bibdata{a}|. Similarly, for every
+\verb|\bibdata| line found, the script will extract the bibliography
+data and add them to a table, even if they are separated by commas,
+like \verb|\bibdata{d,e,f}|. Again, no duplicate values are allowed.
+Stick with this backend if you are using Bib\TeX\ or Bib\LaTeX\ with
+the \verb|backend=bibtex| package option.
+
+\item[\texttt{biber}] With this backend, the script checks
+\verb|.bcf| files (which are XML-based) looking for citations, in the
+form of \verb|bcf:citekey| tags. For every tag found, \checkcites\
+will extract the corresponding values and add them to a table. The
+citation table contains no duplicate values. At the same time
+\checkcites\ also looks for bibliography data, in the form of
+\verb|bcf:datasource| tags. Similarly, for every tag found, the
+script will extract the bibliography data and add them to a table.
+Again, no duplicate values are allowed. Stick with this backend if
+you are using Bib\LaTeX\ with the default options or with the
+\verb|backend=biber| option explicitly set.
+\end{description}
\begin{infoblock}{Attention!}
-If \verb|\citation{*}| is found, \checkcites\ will issue a message
-telling that \verb|\nocite{*}| is in the \verb|.tex| document, but
-the script will do the check nonetheless.
+If \verb|\citation{*}| (Bib\TeX) or simply \verb|*| (Bib\LaTeX)
+is found, \checkcites\ will issue a message telling that
+\verb|\nocite{*}| is in the \verb|.tex| document, but the script will
+do the check nonetheless.
\end{infoblock}
-At the same time \checkcites\ also looks for bibliography data, in the
-form of \verb|\bibdata{a}|. Similarly, for every \verb|\bibdata| line
-found, the script will extract the bibliography data and add them to a
-table, even if they are separated by commas, like
-\verb|\bibdata{d,e,f}|. The table has all duplicate values removed.
+Now, \checkcites\ will extract all entries from the bibliography
+files found in the previous steps, regardless of which backend was
+used. For every element in the bibliography data table, the script
+will look for entries like \verb|@BOOK|, \verb|@ARTICLE| and so
+forth~--~we actually use pattern matching for this~-- and add their
+identifiers to a table. No duplicate values are allowed.
\begin{infoblock}{Attention!}
-If no \verb|\bibdata| command is found, the script ends. There's
-nothing to do in this case.
+If \checkcites\ cannot find a certain bibliography file, the script
+ends. Make sure to put the correct name of the bibliography file in
+your \verb|.tex| file.
\end{infoblock}
-Now, \checkcites\ will extract all entries from the bibliography files
-found in the previous step. For every element in the bibliography data
-table, the script will look for entries like \verb|@BOOK|,
-\verb|@ARTICLE| and so forth --~we actually use pattern matching for
-this~-- and add their identifiers to a table. The script treats all
-\verb|.bib| files as if they were only one. After all files have been
-analyzed and all entries' identifiers extracted, the table has all
-duplicate values removed. Let's call $B$ the set of bibliography
-entries.
-
-\begin{infoblock}{Attention!}
-If \checkcites\ cannot find a certain bibliography file --~that is, a
-\verb|.bib| file~-- the script ends. Make sure to put the correct
-name of the bibliography file in your \verb|.tex| file.
-\end{infoblock}
-
-Now we have both sets $A$ and $B$. In order to get all unused
-references in the \verb|.bib| files, we compute the set difference
+Let there be $A$ and $B$ the sets of citations and references,
+respectively. In order to get all unused references in the
+\verb|.bib| files, we compute the set difference:
\[
B - A = \{ x : x \in B, x \notin A \}.
-\]
-Similarly, in order to get all undefined references in the \verb|.tex|
-file, we compute the set difference
+\]
+Similarly, in order to get all undefined references in the
+\verb|.tex| file, we compute the set difference:
\[
A - B = \{ x : x \in A, x \notin B \}.
\]
If there are either unused or undefined references, \checkcites\ will
-print them in a list format. In Section~\ref{sec:usage} there's a more
-complete explanation on how to use the script.
+print them in a list format. In Section~\ref{sec:usage} there is a
+more complete explanation on how to use the script.
\section{Usage}
\label{sec:usage}
-\checkcites\ is very easy to use. First of all, let's define two files
-that will be used here to explain the script usage. Here's our sample
-bibliography file \verb|example.bib|, with five fictional entries.
+\checkcites\ is very easy to use. First of all, let us define two
+files that will be used here to explain the script usage. Here is our
+sample bibliography file \verb|example.bib|, with five fictional
+entries.
\begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only,
title=Bibliography file, fonttitle=\bfseries,
@@ -176,7 +188,9 @@ bibliography file \verb|example.bib|, with five fictional entries.
}
\end{tcblisting}
-The second file is our main \LaTeX{} document, \verb|document.tex|.
+The second file is our main \LaTeX{} document, \verb|document.tex|.
+Observe that we will stick with Bib\TeX\ for now and check Bib\LaTeX\
+later on.
\begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only,
title=Main document, fonttitle=\bfseries,
@@ -185,7 +199,8 @@ The second file is our main \LaTeX{} document, \verb|document.tex|.
\begin{document}
-Hello world \cite{foo:2012a,foo:2012c}, how are you \cite{foo:2012f},
+Hello world \cite{foo:2012a,foo:2012c},
+how are you \cite{foo:2012f},
and goodbye \cite{foo:2012d,foo:2012a}.
\bibliographystyle{plain}
@@ -200,46 +215,81 @@ Open a terminal and run \verb|checkcites|:
\begin{verbatim}
$ checkcites
\end{verbatim}
-\tcblower
+\tcblower\small
\begin{verbatim}
-checkcites.lua -- a reference checker script (v1.0i)
-Copyright (c) 2012 Enrico Gregorio, Paulo Roberto Massa Cereda
-
-Usage: checkcites.lua [--all | --unused | --undefined] file.aux
-
---all Lists all unused and undefined references.
---unused Lists only unused references in your 'bib' file.
---undefined Lists only undefined references in your 'tex' file.
-
-If no flag is provided, '--all' is set by default.
-Be sure to have all your 'bib' files in the same directory.
+ _ _ _ _
+ ___| |_ ___ ___| |_ ___|_| |_ ___ ___
+| _| | -_| _| '_| _| | _| -_|_ -|
+|___|_|_|___|___|_,_|___|_|_| |___|___|
+
+checkcites.lua -- a reference checker script (v2.0)
+Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda
+
+--------------------------------------------------------------------------
+I am sorry, but you have not provided any command line argument, including
+files to check and options. Make sure to invoke the script with the actual
+arguments. Refer to the user documentation if you are unsure of how this
+tool works. The script will end now.
\end{verbatim}
\end{terminal}
-If you don't have \checkcites\ installed with your \TeX\ distribution,
-you can run the standalone script \verb|checkcites.lua| with either
-\verb|texlua| or \verb|lua|. We recommend to use \verb|texlua|, as
-it's shipped with all the modern \TeX\ distributions:
+If you do not have \checkcites\ installed with your \TeX\
+distribution, you can run the standalone script \verb|checkcites.lua|
+with either \verb|texlua| or \verb|lua|. We recommend to use
+\verb|texlua|, as it is shipped with all the modern \TeX\
+distributions:
\begin{terminal}
\begin{verbatim}
$ texlua checkcites.lua
\end{verbatim}
\end{terminal}
-When you run \checkcites\ without providing any argument to it, the
-script usage will be printed, as seen in the previous output. The only
-required argument is the auxiliary file --~with the \verb|.aux|
-extension~-- which is generated when you compile your main \verb|.tex|
-file. For example, if your main document is named \verb|foo.tex|, you
-probably have a \verb|foo.aux| file too. Let's compile our sample
-document \verb|document.tex|:
+When you run \checkcites\ without providing any argument to it, the a
+message error will appear. Do not panic! Try again with the
+\verb|--help| flag:
+\begin{terminal}
+\begin{verbatim}
+$ checkcites --help
+\end{verbatim}
+\tcblower\small
+\begin{verbatim}
+ _ _ _ _
+ ___| |_ ___ ___| |_ ___|_| |_ ___ ___
+| _| | -_| _| '_| _| | _| -_|_ -|
+|___|_|_|___|___|_,_|___|_|_| |___|___|
+
+checkcites.lua -- a reference checker script (v2.0)
+Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda
+
+Usage: checkcites.lua [ [ --all | --unused | --undefined ] [ --backend
+<arg> ] <file> [ <file 2> ... <file n> ] | --help | --version ]
+
+-a,--all list all unused and undefined references
+-u,--unused list only unused references in your bibliography files
+-U,--undefined list only undefined references in your TeX source file
+-b,--backend <arg> set the backend-based file lookup policy
+-h,--help print the help message
+-v,--version print the script version
+
+Unless specified, the script lists all unused and undefined references by
+default. Also, the default backend is set to "bibtex". Please refer to the
+user documentation for more details.
+\end{verbatim}
+\end{terminal}
+
+Since we are using Bib\TeX, we do not need to set up the
+backend! Simply provide the auxiliary file~--~the one with the
+\verb|.aux| extension~--~which is generated when you compile your
+main \verb|.tex| file. For example, if your main document is named
+\verb|foo.tex|, you probably have a \verb|foo.aux| file too. Let us
+compile our sample document \verb|document.tex|:
\begin{terminal}
\begin{verbatim}
$ pdflatex document.tex
\end{verbatim}
\end{terminal}
-After running \verb|pdflatex| on our \verb|.tex| file, there's now a
+After running \verb|pdflatex| on our \verb|.tex| file, there is now a
\verb|document.aux| file in our work directory.
\begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only,
@@ -261,31 +311,49 @@ Now we can run \checkcites\ on the \verb|document.aux| file:
\begin{verbatim}
$ checkcites document.aux
\end{verbatim}
-\tcblower
+\tcblower\small
\begin{verbatim}
-checkcites.lua -- a reference checker script (v1.0i)
-Copyright (c) 2012 Enrico Gregorio, Paulo Roberto Massa Cereda
+ _ _ _ _
+ ___| |_ ___ ___| |_ ___|_| |_ ___ ___
+| _| | -_| _| '_| _| | _| -_|_ -|
+|___|_|_|___|___|_,_|___|_|_| |___|___|
+
+checkcites.lua -- a reference checker script (v2.0)
+Copyright (c) 2012, 2017, Enrico Gregorio, Paulo Roberto Massa Cereda
-I found 4 citation(s).
-Great, there's only one 'bib' file. Let me check it.
-I found 5 reference(s).
+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.
-Unused reference(s) in your bibliography file(s): 2
-- foo:2012b
-- foo:2012e
+Fantastic, I found 5 references in 1 bibliography file. Please wait a
+moment while the reports are generated.
-Undefined reference(s) in your TeX file: 1
-- foo:2012f
+--------------------------------------------------------------------------
+Report of unused references in your TeX document (that is, references
+present in bibliography files, but not cited in the TeX source file)
+--------------------------------------------------------------------------
+
+Unused references in your TeX document: 2
+=> foo:2012b
+=> foo:2012e
+
+--------------------------------------------------------------------------
+Report of undefined references in your TeX document (that is, references
+cited in the TeX source file, but not present in the bibliography files)
+--------------------------------------------------------------------------
+
+Undefined references in your TeX document: 1
+=> foo:2012f
\end{verbatim}
\end{terminal}
-As we can see in the script output, \checkcites\ analyzed both
-\verb|.aux| and \verb|.bib| files and found two unused references in
-the bibliography file --~\verb|foo:2012b| and \verb|foo:2012e|~-- and
-one undefined reference in the document --~\verb|foo:2012f|.
+As we can see in the script output, \checkcites\ analyzed
+both \verb|.aux| and \verb|.bib| files and managed to find two
+unused references in the bibliography file~--~\verb|foo:2012b|
+and \verb|foo:2012e|~--~and one undefined reference in the
+document~--~\verb|foo:2012f|.
-\checkcites\ allows a command line switch that will tell it how to
-behave. For example,
+\checkcites\ allows a couple of command line flags that will tell it
+how to behave. For example, check this command line:
\begin{terminal}
\begin{verbatim}
@@ -293,9 +361,9 @@ $ checkcites --unused document.aux
\end{verbatim}
\end{terminal}
-The \verb|--unused| flag will make the script only look for unused
-references in the \verb|.bib| file. The argument order doesn't matter,
-you can also run
+The \verb|--unused| flag will make the script only look for unused
+references in the \verb|.bib| file. The argument order does not
+matter, you can also run:
\begin{terminal}
\begin{verbatim}
@@ -303,7 +371,7 @@ $ checkcites document.aux --unused
\end{verbatim}
\end{terminal}
-The script will behave the same. Similarly, you can use
+The script will behave the same. Similarly, you can use:
\begin{terminal}
\begin{verbatim}
@@ -311,9 +379,9 @@ $ checkcites --undefined document.aux
\end{verbatim}
\end{terminal}
-The \verb|--undefined| flag will make the script only look for
-undefined references in the \verb|.tex| file. If you want \checkcites\
-to look for both unused and undefined references, run:
+The \verb|--undefined| flag will make the script only look
+for undefined references in the \verb|.tex| file. If you want
+\checkcites\ to look for both unused and undefined references, run:
\begin{terminal}
\begin{verbatim}
@@ -321,15 +389,113 @@ $ checkcites --all document.aux
\end{verbatim}
\end{terminal}
-If no special argument is provided, the \verb|--all| flag is set as default.
+If no special argument is provided, the \verb|--all| flag is set as
+default.
+
+Observe that our example relied on the default backend, which
+uses Bib\TeX. Let us change our document a bit to make it
+Bib\LaTeX-compliant:
+
+\begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only,
+ title=Main document, fonttitle=\bfseries,
+ listing options={columns=fullflexible,basicstyle=\ttfamily}}
+\documentclass{article}
+
+\usepackage{biblatex}
+\addbibresource{example.bib}
+
+\begin{document}
+
+Hello world \cite{foo:2012a,foo:2012c},
+how are you \cite{foo:2012f},
+and goodbye \cite{foo:2012d,foo:2012a}.
+
+\printbibliography
+
+\end{document}
+\end{tcblisting}
+
+As usual, let's compile our sample document \verb|document.tex|:
+
+\begin{terminal}
+\begin{verbatim}
+$ pdflatex document.tex
+\end{verbatim}
+\end{terminal}
+
+After running \verb|pdflatex| on our \verb|.tex| file, there is now a
+\verb|document.aux| file in our work directory, as expected. However,
+since we are using Bib\LaTeX\ as well, there is another file of
+interest in our working directory, one that has a \verb|.bcf|
+extension! In order to run \checkcites\ on that specific file, we
+need to provide the \verb|biber| backend:
+
+\begin{terminal}
+\begin{verbatim}
+$ checkcites --backend biber document.bcf
+\end{verbatim}
+\end{terminal}
+
+We can even omit the file extension, the script will automatically
+assign one based on the current backend:
+
+\begin{terminal}
+\begin{verbatim}
+$ checkcites --backend biber document
+\end{verbatim}
+\end{terminal}
+
+Now, let us run \checkcites\ on the \verb|.bcf| file, providing the
+\verb|biber| backend:
+
+\begin{terminal}
+\begin{verbatim}
+$ checkcites --backend biber document.bcf
+\end{verbatim}
+\tcblower\small
+\begin{verbatim}
+ _ _ _ _
+ ___| |_ ___ ___| |_ ___|_| |_ ___ ___
+| _| | -_| _| '_| _| | _| -_|_ -|
+|___|_|_|___|___|_,_|___|_|_| |___|___|
+
+checkcites.lua -- a reference checker script (v2.0)
+Copyright (c) 2012, 2017, 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.
+
+Fantastic, I found 5 references in 1 bibliography file. Please wait a
+moment while the reports are generated.
+
+--------------------------------------------------------------------------
+Report of unused references in your TeX document (that is, references
+present in bibliography files, but not cited in the TeX source file)
+--------------------------------------------------------------------------
+
+Unused references in your TeX document: 2
+=> foo:2012b
+=> foo:2012e
+
+--------------------------------------------------------------------------
+Report of undefined references in your TeX document (that is, references
+cited in the TeX source file, but not present in the bibliography files)
+--------------------------------------------------------------------------
+
+Undefined references in your TeX document: 1
+=> foo:2012f
+\end{verbatim}
+\end{terminal}
+
+That is all, folks!
\section{License}
\label{sec:license}
-This script is licensed under the
-\href{http://www.latex-project.org/lppl/}{LaTeX Project Public
-License}. If you want to support \LaTeX{} development by a donation,
-the best way to do this is donating to the
+This script is licensed under the
+\href{http://www.latex-project.org/lppl/}{\LaTeX\ Project Public
+License}. If you want to support \LaTeX{} development by a
+donation, the best way to do this is donating to the
\href{http://www.tug.org/}{TeX Users Group}.
\begin{infoblock}{Official code repository}
diff --git a/Master/texmf-dist/scripts/checkcites/checkcites.lua b/Master/texmf-dist/scripts/checkcites/checkcites.lua
index 69d79e172da..cdd0df14ef9 100755
--- a/Master/texmf-dist/scripts/checkcites/checkcites.lua
+++ b/Master/texmf-dist/scripts/checkcites/checkcites.lua
@@ -1,684 +1,721 @@
#!/usr/bin/env texlua
--- ******************************************************************
+-- -----------------------------------------------------------------
-- checkcites.lua
--- Copyright 2012 Enrico Gregorio, Paulo Roberto Massa Cereda
+-- Copyright 2012, 2017, 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 license or (at your option) any later version.
+-- 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 Maintainers of this work are the original authors.
+-- 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 consists of the file checkcites.lua.
+-- This work has the LPPL maintenance status `maintained'. the
+-- current maintainers of this work are the original authors. This
+-- work consists of the file checkcites.lua.
--
--- Project page: http://github.com/cereda/checkcites
--- ******************************************************************
-
--- version and date, to be updated on each release/commit
-VERSION = "1.0i"
-DATE = "December 18, 2012"
-
--- globals
--- warning about \citation{*}
-globalAsteriskWarning = true
-
--- The following code adds a 'split' function to the string type,
--- thanks to the codebase available here:
--- http://lua-users.org/wiki/SplitJoin
-string.split = function(str, pattern)
-
- pattern = pattern or "[^%s]+"
-
- if pattern:len() == 0 then
-
- pattern = "[^%s]+"
-
+-- Project repository: http://github.com/cereda/checkcites
+-- -----------------------------------------------------------------
+
+-- Checks if the table contains the element.
+-- @param a Table.
+-- @param hit Element.
+-- @return Boolean value if the table contains the element.
+local function exists(a, hit)
+ for _, v in ipairs(a) do
+ if v == hit then
+ return true
end
-
- local parts = {__index = table.insert}
-
- setmetatable(parts, parts)
-
- str:gsub(pattern, parts)
-
- setmetatable(parts, nil)
-
- parts.__index = nil
-
- return parts
-
+ end
+ return false
end
--- In order to make our lives easier, we borrowed the following
--- codes for implementing common set operations, available here:
--- http://www.phailed.me/2011/02/common-set-operations-in-lua/
-function setFind(a, tbl)
-
- for _,a_ in ipairs(tbl) do
-
- if a_==a then
-
- return true
+-- Parses the list of arguments based on a configuration map.
+-- @param map Configuration map.
+-- @param args List of command line arguments.
+-- @return Table containing the valid keys and entries.
+-- @return Table containing the invalid keys.
+local function parse(map, args)
+ local keys, key, unknown = {}, 'unpaired', {}
+ local a, b
+ for _, v in ipairs(args) do
+ a, _, b = string.find(v, '^%-(%w)$')
+ if a then
+ for _, x in ipairs(map) do
+ key = 'unpaired'
+ if x['short'] == b then
+ key = x['long']
+ break
end
-
- end
-
-end
-
--- This code returns a table containing the difference between
--- the two other tables, also available here:
--- http://www.phailed.me/2011/02/common-set-operations-in-lua/
-function setDifference(a, b)
-
- local ret = {}
-
- for _,a_ in ipairs(a) do
-
- if not setFind(a_,b) then
-
- table.insert(ret, a_)
-
+ end
+ if key == 'unpaired' then
+ table.insert(unknown, '-' .. b)
+ end
+ if not keys[key] then
+ keys[key] = {}
+ end
+ else
+ a, _, b = string.find(v, '^%-%-([%w-]+)$')
+ if a then
+ for _, x in ipairs(map) do
+ key = 'unpaired'
+ if x['long'] == b then
+ key = b
+ break
+ end
end
-
- end
-
- return ret
-
-end
-
--- Code to remove duplicates from a table array.
-function removeDuplicates(tb)
-
- -- new table
- local ret = {}
-
- -- flag to spot new insertions
- local flag
-
- -- set local variables
- local i
- local k
- local j
- local l
-
- -- iterate through the original table
- for i, k in pairs(tb) do
-
- -- at first, insert element
- flag = true
-
- -- iterate through the new table
- for j, l in pairs(ret) do
-
- -- if the element already exists
- if k == l then
-
- -- set flag to false, so the
- -- new element won't be inserted
- flag = false
-
- end
-
+ if key == 'unpaired' then
+ if not exists(unknown, '--' .. b) then
+ table.insert(unknown, '--' .. b)
+ end
end
-
- -- if it's ok to insert
- if flag then
-
- -- insert new element
- table.insert(ret, k)
-
+ if not keys[key] then
+ keys[key] = {}
end
-
- end
-
- -- return new table
- return ret
-end
-
--- This function opens and gets all data from the provided
--- aux file.
--- Return:
--- * list of citations
--- * list of bibfiles
-function getDataFromAuxFile(theAuxFile)
-
- -- open a file handler
- local fileHandler = io.open(theAuxFile,"r")
-
- -- check if the handler is valid
- if fileHandler then
-
- -- create a local table for citations
- local theCitations = {}
-
- -- and a local reference to the bib file
- local theBibFiles = {}
-
- -- define local variables
- local currentLine
- local citation
- local index
- local theCitation
- local theBibFile
- local entry
-
- -- now let's iterate through the lines
- for currentLine in fileHandler:lines() do
-
- -- if the citation matches, extract it
- for citation in string.gmatch(currentLine, '\\citation{(.+)}') do
-
- -- sanity check, in case it's an '*'
- if citation ~= "*" then
-
- -- break the citations list, in case of multiple
- -- citations in the same \citation{}
- local parts = string.split(citation, "[^,%s]+" )
-
- -- for every entry in the citations list
- for index, theCitation in pairs(parts) do
-
- -- insert the reference
- table.insert(theCitations, theCitation)
-
- end
-
- -- found a '*'
- else
-
- -- check if warning is still valid, that is,
- -- if not displayed yet
- if globalAsteriskWarning then
-
- -- show message
- print("Warning: '\\nocite{*}' found, I'll do the check nonetheless.\n")
-
- -- warning already displayed, so
- -- set flag to false
- globalAsteriskWarning = false
-
- end
-
- end
-
- -- end of citation in current line
- end
-
- -- in the same current line, check if there's the
- -- bibdata entry and extract it
- for entry in string.gmatch(currentLine, '\\bibdata{(.+)}') do
-
- -- break the bib files list, in case of multiple
- -- files in the same \bibdata{}
- local parts = string.split(entry, "[^,%s]+" )
-
- -- for every entry in the bib files list
- for index, theBibFile in pairs(parts) do
-
- -- insert the file
- table.insert(theBibFiles, theBibFile)
-
- end
-
- -- end of bib files in the current line
- end
-
- -- end of current line
+ else
+ if not keys[key] then
+ keys[key] = {}
end
-
- -- close the file handler
- fileHandler:close()
-
- -- remove duplicated citations
- theCitations = removeDuplicates(theCitations)
-
- -- print a message about the citations
- print("I found " .. #theCitations .. " citation(s).")
-
- -- remove possible duplicated files
- theBibFiles = removeDuplicates(theBibFiles)
-
- -- if there are no bib files
- if #theBibFiles == 0 then
-
- -- show message
- print("I couldn't find any bibliography files.\nI'm afraid I have nothing to do now.")
-
- -- and abort the script
- os.exit()
-
- -- if there is only one bib file
- elseif #theBibFiles == 1 then
-
- -- show message
- print("Great, there's only one 'bib' file. Let me check it.")
-
- -- there are more bib files
+ if key ~= 'unpaired' then
+ for _, x in ipairs(map) do
+ if x['long'] == key then
+ if not (x['argument'] and
+ #keys[key] == 0) then
+ key = 'unpaired'
+ end
+ break
+ end
+ end
+ if not keys[key] then
+ keys[key] = {}
+ end
+ table.insert(keys[key], v)
else
-
- -- show message
- print("Oh no, I have to check more than one 'bib' file. Please wait.")
-
+ if not keys[key] then
+ keys[key] = {}
+ end
+ table.insert(keys[key], v)
end
-
- -- return both citations and bib files
- return theCitations, theBibFiles
-
- -- the file handler is invalid
- else
-
- -- print an error message
- print("File '" .. theAuxFile .. "' does not exist or is unavailable. Aborting script.")
-
- -- and abort the script
- os.exit()
-
+ end
end
-
--- end of function
+ end
+ return keys, unknown
end
--- This function opens and gets all data from all the available
--- bib files.
-function getDataFromBibFiles(theBibFiles)
-
- -- create a table to store the citations
- local theReferences = {}
-
- -- set local variables
- local index
- local theBibFile
- local currentLine
- local reference
-
- -- iterate through all bib files
- for index, theBibFile in pairs(theBibFiles) do
-
- -- open the bib file
- local fileHandler = io.open(theBibFile .. ".bib","r")
-
- -- check if the handler is valid
- if fileHandler then
-
- -- iterate through every line of the bib file
- for currentLine in fileHandler:lines() do
-
- -- if a reference is found
- for reference in string.gmatch(currentLine, '@%w+{%s*(.+),') do
-
- -- insert the reference
- table.insert(theReferences, reference)
-
- end
-
- -- end current line
- end
-
- -- close the file handler
- fileHandler:close()
-
- -- bib file does not exist
- else
-
- -- error message
- print("File '" .. theBibFile .. ".bib' does not exist. Aborting.")
-
- -- abort script
- os.exit()
-
- end
-
- -- end iteration through the bib files
+-- Calculates the difference between two tables.
+-- @param a First table.
+-- @param b Second table.
+-- @return Table containing the difference between two tables.
+local function difference(a, b)
+ local result = {}
+ for _, v in ipairs(a) do
+ if not exists(b, v) then
+ table.insert(result, v)
end
-
- -- remove duplicated references
- theReferences = removeDuplicates(theReferences)
-
- -- print message
- print("I found " .. #theReferences .. " reference(s).")
-
- -- return references
- return theReferences
-
--- end of function
+ end
+ return result
end
--- This function show all the undefined references. It's very
--- simple, it's a difference between two sets.
-function showUndefinedReferences(citations, references)
-
- -- get all undefined references
- local undefined = setDifference(citations, references)
-
- -- print message
- print("\nUndefined reference(s) in your TeX file: " .. #undefined)
-
- -- if there are undefined references
- if #undefined ~= 0 then
-
- -- local variables
- local index
- local reference
-
- -- iterate
- for index, reference in pairs(undefined) do
-
- -- and print
- print("- " .. reference)
-
- end
+-- Splits the string based on a pattern.
+-- @param str String.
+-- @param pattern Pattern.
+local function split(str, pattern)
+ local result = {}
+ string.gsub(str, pattern, function(a)
+ table.insert(result, a) end)
+ return result
+end
+-- Reads lines from a file.
+-- @param file File.
+-- @returns Table representing the lines.
+local function read(file)
+ local handler = io.open(file, 'r')
+ local lines = {}
+ if handler then
+ for line in handler:lines() do
+ table.insert(lines, line)
end
-
--- end of function
+ handler:close()
+ end
+ return lines
end
--- This function show all the unused references. It's very
--- simple, it's a difference between two sets.
-function showUnusedReferences(citations, references)
-
--- get all undefined references
- local unused = setDifference(references, citations)
-
- -- print message
- print("\nUnused reference(s) in your bibliography file(s): " .. #unused)
-
- -- if there are unused references
- if #unused ~= 0 then
-
- -- local variables
- local index
- local reference
-
- -- iterate
- for index, reference in pairs(unused) do
-
- -- and print
- print("- " .. reference)
+-- Normalizes the string, removing leading and trailing spaces.
+-- @param str String.
+-- @return Normalized string without leading and trailing spaces.
+local function normalize(str)
+ local result, _ = string.gsub(str, '^%s', '')
+ result, _ = string.gsub(result, '%s$', '')
+ return result
+end
- end
-
+-- Checks if the element is in a blacklist.
+-- @param a Element.
+-- @return Boolean value if the element is blacklisted.
+local function blacklist(a)
+ local list = {}
+ for _, v in ipairs(list) do
+ if v == a then
+ return true
end
-
--- end of function
+ end
+ return false
end
--- This function parses the command line arguments and returns a
--- bunch of info for us to use.
--- Return:
--- * an argument code
--- * the filename
--- * an action code
-function parseArguments(theArgs)
-
- -- check if there are no arguments
- if #theArgs == 0 then
-
- -- return usage code
- return 0, nil, nil
-
- -- there is one argument
- elseif #theArgs == 1 then
-
- -- check if it's help
- if theArgs[1] == "--help" then
-
- -- return help code
- return 1, nil, nil
-
- -- check if it's version
- elseif theArgs[1] == "--version" then
-
- -- return version code
- return 2, nil, nil
-
- -- check if it's invalid
- elseif string.sub(theArgs[1], 1, 1) == "-" then
-
- -- return invalid code
- return 3, nil, nil
-
- -- it seems a clean argument
- else
+-- 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
+ if not exists(result, hit) then
+ hit = normalize(hit)
+ table.insert(result, hit)
+ end
+ end
+ end
+ return result
+end
- -- return it as a valid argument
- return 4, theArgs[1], nil
+-- 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
- -- end for one parameter
+-- Backend namespace
+local backends = {}
+
+-- Gets data from auxiliary files (BibTeX).
+-- @param lines Lines of a file.
+-- @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 = {}, {}
+ local asterisk, parts, hit = false
+ for _, line in ipairs(lines) do
+ hit = string.match(line, '^%s*\\citation{(.+)}$')
+ if hit then
+ if hit ~= '*' then
+ parts = split(hit, '[^,%s]+')
+ for _, v in ipairs(parts) do
+ v = normalize(v)
+ if not exists(citations, v) then
+ table.insert(citations, v)
+ end
end
-
- -- there are two arguments
- elseif #theArgs == 2 then
-
- -- check if both are valid
- if ((theArgs[1] == "--all" or theArgs[1] == "--unused" or theArgs[1] == "--undefined") and string.sub(theArgs[2], 1, 1) ~= "-") or ((theArgs[2] == "--all" or theArgs[2] == "--unused" or theArgs[2] == "--undefined") and string.sub(theArgs[1], 1, 1) ~= "-") then
-
- -- create an action code
- local actionCode
-
- -- check which one is the file name
- if string.sub(theArgs[1], 1, 1) ~= "-" then
-
- -- check for --all
- if theArgs[2] == "--all" then
-
- -- set the action code
- actionCode = 0
-
- -- check for --unused
- elseif theArgs[2] == "--unused" then
-
- -- set the action code
- actionCode = 1
-
- -- it's --undefined
- else
-
- -- set the action code
- actionCode = 2
-
- end
-
- -- it's the first
- return 4, theArgs[1], actionCode
-
- else
-
- -- check for --all
- if theArgs[1] == "--all" then
-
- -- set the action code
- actionCode = 0
-
- -- check for --unused
- elseif theArgs[1] == "--unused" then
-
- -- set the action code
- actionCode = 1
-
- else
-
- -- it's --undefined
- actionCode = 2
-
- end
-
- -- it's the second
- return 4, theArgs[2], actionCode
-
- end
-
- else
-
- -- return invalid code
- return 3, nil, nil
-
+ else
+ asterisk = true
+ end
+ else
+ hit = string.match(line, '^%s*\\bibdata{(.+)}$')
+ if hit then
+ parts = split(hit, '[^,%s]+')
+ for _, v in ipairs(parts) do
+ v = normalize(v)
+ if not exists(bibliography, v) and
+ not blacklist(v) then
+ table.insert(bibliography, v)
+ end
end
+ end
+ end
+ end
+ return asterisk, citations, bibliography
+end
+-- Gets data from auxiliary files (Biber).
+-- @param lines Lines of a file.
+-- @return Boolean indicating if an asterisk was found.
+-- @return Table containing the citations.
+-- @return Table containing the bibliography files.
+backends.biber = function(lines)
+ local citations, bibliography = {}, {}
+ local asterisk, parts, hit = false
+ for _, line in ipairs(lines) do
+ hit = string.match(line, '^%s*<bcf:citekey order="%d+">' ..
+ '(.+)</bcf:citekey>$')
+ if hit then
+ if hit ~= '*' then
+ parts = split(hit, '[^,%s]+')
+ for _, v in ipairs(parts) do
+ v = normalize(v)
+ if not exists(citations, v) then
+ table.insert(citations, v)
+ end
+ end
+ else
+ asterisk = true
+ end
else
-
- -- more than two arguments, return usage code
- return 0, nil, nil
-
+ hit = string.match(line, '^%s*<bcf:datasource type="file" ' ..
+ 'datatype="%w+">(.+)</bcf:datasource>$')
+ if hit then
+ parts = split(hit, '[^,%s]+')
+ for _, v in ipairs(parts) do
+ v = normalize(v)
+ if not exists(bibliography, v) and
+ not blacklist(v) then
+ table.insert(bibliography, v)
+ end
+ end
+ end
end
-
--- end of function
+ end
+ return asterisk, citations, bibliography
end
--- This function prints the script header.
-function printHeader()
-
- -- print message
- print("checkcites.lua -- a reference checker script (v" .. VERSION .. ")")
- print("Copyright (c) 2012 Enrico Gregorio, Paulo Roberto Massa Cereda\n")
-
--- end of function
+-- Counts the number of elements of a nominal table.
+-- @param t Table.
+-- @return Table size.
+local function count(t)
+ local counter = 0
+ for _, _ in pairs(t) do
+ counter = counter + 1
+ end
+ return counter
end
--- This function prints the script usage
-function printUsage()
-
- -- show message
- print("Usage: " .. arg[0] .. " [--all | --unused | --undefined] file.aux\n")
- print("--all Lists all unused and undefined references.")
- print("--unused Lists only unused references in your 'bib' file.")
- print("--undefined Lists only undefined references in your 'tex' file.\n")
- print("If no flag is provided, '--all' is set by default.")
- print("Be sure to have all your 'bib' files in the same directory.")
-
--- end of function
+-- Repeats the provided char a certain number of times.
+-- @param c Char.
+-- @param w Number of times.
+-- @return String with a char repeated a certain number of times.
+local function pad(c, w)
+ local r = c
+ while #r < w do
+ r = r .. c
+ end
+ return r
end
-function printHelp()
-
- -- show message
- print("checkcites.lua is a Lua script written for the sole purpose of")
- print("detecting undefined/unused references from LaTeX auxiliary or")
- print("bibliography files. It's very easy to use!\n")
-
- -- print usage
- printUsage()
-
--- end of function
+-- 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
--- This function prints the script version.
-function printVersion()
-
- -- print message
- print("checkcites.lua version " .. VERSION .. " (dated " .. DATE .. ")")
- print("You can find more information about this script in the official")
- print("source code repository:\n")
- print("http://github.com/cereda/checkcites\n")
- print("checkcites.lua is licensed under the LaTeX Project Public License.")
-
--- end of function
+-- Flattens a table of tables into only one table.
+-- @param t Table.
+-- @return Flattened table.
+local function flatten(t)
+ local result = {}
+ for _, v in ipairs(t) do
+ for _, k in ipairs(v) do
+ if not exists(result, k) then
+ table.insert(result, k)
+ end
+ end
+ end
+ return result
end
--- This function prints a message for invalid parameters.
-function printInvalid()
-
- -- print message
- print("Oh no, it seems you used an invalid argument.\n")
-
- -- print usage
- printUsage()
-
--- end of function
+-- Applies a function to elements of a table.
+-- @param c Table.
+-- @param f Function.
+-- @return A new table.
+local function apply(c, f)
+ local result = {}
+ for _, v in ipairs(c) do
+ table.insert(result, f(v))
+ end
+ return result
end
--- This is our main function.
-function runMain(theArgs)
-
- -- print the script header
- printHeader()
-
- -- set local variables
- local argCode
- local fileName
- local actionCode
-
- -- parse arguments and get the result
- argCode, fileName, actionCode = parseArguments(theArgs)
-
- -- check for usage
- if argCode == 0 then
-
- -- print usage
- printUsage()
-
- -- it's help
- elseif argCode == 1 then
-
- -- print help
- printHelp()
-
- -- it's version
- elseif argCode == 2 then
-
- -- print version
- printVersion()
-
- -- it's an invalid parameter
- elseif argCode == 3 then
-
- -- print invalid
- printInvalid()
-
- -- it's a valid operation
+-- 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
- -- get data from aux
- a, b = getDataFromAuxFile(fileName)
-
- -- get data from bib
- c = getDataFromBibFiles(b)
-
- -- if there is an action code
- if actionCode ~= nil then
-
- -- it's --all
- if actionCode == 0 then
-
- -- do everything
- showUnusedReferences(a,c)
- showUndefinedReferences(a,c)
-
- -- it's --unused
- elseif actionCode == 1 then
+-- Prints the script header.
+local function header()
+print(" _ _ _ _")
+print(" ___| |_ ___ ___| |_ ___|_| |_ ___ ___")
+print("| _| | -_| _| '_| _| | _| -_|_ -|")
+print("|___|_|_|___|___|_,_|___|_|_| |___|___|")
+print()
+ print(wrap('checkcites.lua -- a reference ' ..
+ 'checker script (v2.0)', 74))
+ print(wrap('Copyright (c) 2012, 2017, ' ..
+ 'Enrico Gregorio, Paulo ' ..
+ 'Roberto Massa Cereda', 74))
+end
- -- only show unused
- showUnusedReferences(a,c)
+-- Operation namespace
+local operations = {}
+
+-- Reports the unused references.
+-- @param citations Citations.
+-- @param references References.
+-- @return Integer representing the status.
+operations.unused = function(citations, references)
+ print()
+ print(pad('-', 74))
+ print(wrap('Report of unused references in your TeX ' ..
+ 'document (that is, references present in ' ..
+ 'bibliography files, but not cited in ' ..
+ 'the TeX source file)', 74))
+ print(pad('-', 74))
+ local r = difference(references, citations)
+ print()
+ print(wrap('Unused references in your TeX document: ' ..
+ tostring(#r), 74))
+ if #r == 0 then
+ return 0
+ else
+ for _, v in ipairs(r) do
+ print('=> ' .. v)
+ end
+ return 1
+ end
+end
- -- it's --undefined
- else
+-- Reports the undefined references.
+-- @param citations Citations.
+-- @param references References.
+-- @return Integer value indicating the status.
+operations.undefined = function(citations, references)
+ print()
+ print(pad('-', 74))
+ print(wrap('Report of undefined references in your TeX ' ..
+ 'document (that is, references cited in the ' ..
+ 'TeX source file, but not present in the ' ..
+ 'bibliography files)', 74))
+ print(pad('-', 74))
+ local r = difference(citations, references)
+ print()
+ print(wrap('Undefined references in your TeX document: ' ..
+ tostring(#r), 74))
+ if #r == 0 then
+ return 0
+ else
+ for _, v in ipairs(r) do
+ print('=> ' .. v)
+ end
+ return 1
+ end
+end
- -- only show undefined
- showUndefinedReferences(a,c)
+-- Reports both unused and undefined references.
+-- @param citations Citations.
+-- @param references References.
+-- @return Integer value indicating the status.
+operations.all = function(citations, references)
+ local x, y
+ x = operations.unused(citations, references)
+ y = operations.undefined(citations, references)
+ if x + y > 0 then
+ return 1
+ else
+ return 0
+ end
+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
- -- there's only one parameter, the file name,
- -- so we set --all
- else
+-- Filters a table of files, keeping the inexistent ones.
+-- @param files Table.
+-- @return Table of inexistent files.
+local function validate(files)
+ local result = {}
+ for _, v in ipairs(files) do
+ if not valid(v) then
+ table.insert(result, v)
+ end
+ end
+ return result
+end
- -- show everything
- showUnusedReferences(a,c)
- showUndefinedReferences(a,c)
+-- Main function.
+-- @param args Command line arguments.
+-- @return Integer value indicating the status
+local function checkcites(args)
+ header()
+
+ local parameters = {
+ { short = 'a', long = 'all', argument = false },
+ { short = 'u', long = 'unused', argument = false },
+ { short = 'U', long = 'undefined', argument = false },
+ { short = 'v', long = 'version', argument = false },
+ { short = 'h', long = 'help', argument = false },
+ { short = 'b', long = 'backend', argument = true }
+ }
+
+ local keys, err = parse(parameters, args)
+ local check, backend = 'all', 'bibtex'
+
+ if #err ~= 0 then
+ print()
+ print(pad('-', 74))
+ print(wrap('I am sorry, but I do not recognize ' ..
+ 'the following ' .. plural(#err, 'option',
+ 'options') .. ':', 74))
+ for _, v in ipairs(err) do
+ print('=> ' .. v)
+ end
- end
+ print()
+ print(wrap('Please make sure to use the correct ' ..
+ 'options when running this script. You ' ..
+ 'can also refer to the user documentation ' ..
+ 'for a list of valid options. The script ' ..
+ 'will end now.', 74))
+ return 1
+ end
+
+ if count(keys) == 0 then
+ print()
+ print(pad('-', 74))
+ print(wrap('I am sorry, but you have not provided ' ..
+ 'any command line argument, including ' ..
+ 'files to check and options. Make ' ..
+ 'sure to invoke the script with the actual ' ..
+ 'arguments. Refer to the user documentation ' ..
+ 'if you are unsure of how this tool ' ..
+ 'works. The script will end now.', 74))
+ return 1
+ end
+
+ 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(pad('-', 74))
+ print(wrap('You can find more details about this ' ..
+ 'script, as well as the user documentation, ' ..
+ 'in the official source code repository:', 74))
+
+ print()
+ print('https://github.com/cereda/checkcites')
+
+ print()
+ print(wrap('The checkcites.lua script is licensed ' ..
+ 'under the LaTeX Project Public License, ' ..
+ 'version 1.3. The current maintainers ' ..
+ 'are the original authors.', 74))
+ else
+ print()
+ print(wrap('Usage: ' .. args[0] .. ' [ [ --all | --unused | ' ..
+ '--undefined ] [ --backend <arg> ] <file> [ ' ..
+ '<file 2> ... <file n> ] | --help | --version ' ..
+ ']', 74))
+
+ print()
+ print('-a,--all list all unused and undefined references')
+ print('-u,--unused list only unused references in your bibliography files')
+ print('-U,--undefined list only undefined references in your TeX source file')
+ print('-b,--backend <arg> set the backend-based file lookup policy')
+ print('-h,--help print the help message')
+ print('-v,--version print the script version')
+
+ print()
+ print(wrap('Unless specified, the script lists all unused and ' ..
+ 'undefined references by default. Also, the default ' ..
+ 'backend is set to "bibtex". Please refer to the user ' ..
+ 'documentation for more details.', 74))
+ end
+ return 0
+ end
+
+ if not keys['unpaired'] then
+ print()
+ print(pad('-', 74))
+ print(wrap('I am sorry, but you have not provided ' ..
+ 'files to process. The tool requires ' ..
+ 'least one file in order to properly ' ..
+ 'work. Make sure to invoke the script ' ..
+ 'with an actual file (or files). Refer ' ..
+ 'to the user documentation if you are ' ..
+ 'unsure of how this tool works. The ' ..
+ 'script will end now.', 74))
+ return 1
+ end
+
+ if keys['backend'] then
+ if not exists({ 'bibtex', 'biber' }, keys['backend'][1]) then
+ print()
+ print(pad('-', 74))
+ print(wrap('I am sorry, but you provided an ' ..
+ 'invalid backend. I know two: ' ..
+ '"bibtex" (which is the default ' ..
+ 'one) and "biber". Please make ' ..
+ 'sure to select one of the two. ' ..
+ 'Also refer to the user documentation ' ..
+ 'for more information on how these ' ..
+ 'backends work. The script will end ' ..
+ 'now.', 74))
+ return 1
+ else
+ backend = keys['backend'][1]
+ end
+ end
+
+ if not keys['all'] then
+ if keys['unused'] and keys['undefined'] then
+ check = 'all'
+ elseif keys['unused'] or keys['undefined'] then
+ check = (keys['unused'] and 'unused') or
+ (keys['undefined'] and 'undefined')
+ end
+ end
+
+ local auxiliary = apply(keys['unpaired'], function(a)
+ return sanitize(a, (backend == 'bibtex'
+ and 'aux') or 'bcf') end)
+
+ local vld = validate(auxiliary)
+ if #vld ~= 0 then
+ print()
+ print(pad('-', 74))
+ print(wrap('I am sorry, but I was unable to ' ..
+ 'locate ' .. plural(#vld, 'this file',
+ 'these files') .. ' (the extension ' ..
+ 'is automatically set based on the ' ..
+ '"' .. backend .. '" backend):', 74))
+ for _, v in ipairs(vld) do
+ print('=> ' .. v)
+ end
+ print()
+ print(wrap('Selected backend: ' .. backend, 74))
+ print(wrap('File lookup policy: add ".' ..
+ ((backend == 'bibtex' and 'aux') or 'bcf') ..
+ '" to files if not provided.', 74))
+
+ print()
+ print(wrap('Please make sure the ' .. plural(#vld,
+ 'path is', 'paths are') .. ' ' ..
+ 'correct and the ' .. plural(#vld,
+ '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,
+ 'this is not the file', 'these are not the ' ..
+ 'files') .. ' you were expecting, ' ..
+ 'double-check your source file or ' ..
+ 'change the backend option when running ' ..
+ 'this tool. The script will end now.', 74))
+ return 1
+ end
+
+ local lines = flatten(apply(auxiliary, read))
+ local asterisk, citations, bibliography = backends[backend](lines)
+
+ print()
+ print(wrap('Great, I found ' .. tostring(#citations) .. ' ' ..
+ plural(#citations, 'citation', 'citations') .. ' in ' ..
+ tostring(#auxiliary) .. ' ' .. plural(#auxiliary, 'file',
+ 'files') ..'. I also found ' .. tostring(#bibliography) ..
+ ' ' .. 'bibliography ' .. plural(#bibliography, 'file',
+ 'files') .. '. Let me check ' .. plural(#bibliography,
+ 'this file', 'these files') .. ' and extract the ' ..
+ 'references. Please wait a moment.', 74))
+
+ if asterisk then
+ print()
+ print(wrap('Also, it is worth noticing that I found a mention to ' ..
+ 'a special "*" when retrieving citations. That means ' ..
+ 'your TeX document contains "\\nocite{*}" somewhere in ' ..
+ 'the source code. I will continue with the check ' ..
+ 'nonetheless.', 74))
+ end
+
+ bibliography = apply(bibliography, function(a)
+ return sanitize(a, 'bib') end)
+
+ vld = validate(bibliography)
+ if #vld ~= 0 then
+ print()
+ print(pad('-', 74))
+ print(wrap('I am sorry, but I was unable to locate ' ..
+ plural(#vld, 'this file', 'these files') .. ' ' ..
+ '(the extension is automatically set to ' ..
+ '".bib", if not provided):', 74))
+ for _, v in ipairs(vld) do
+ print('=> ' .. v)
end
--- end of function
+ print()
+ print(wrap('Please make sure the ' .. plural(#vld,
+ 'path is', 'paths are') .. ' ' ..
+ 'correct and the ' .. plural(#vld,
+ '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',
+ 'these are not the files') .. ' you were ' ..
+ 'expecting (wrong bibliography), double-check ' ..
+ 'your source file. The script will end ' ..
+ 'now.', 74))
+ return 1
+ end
+
+ local references = flatten(apply(bibliography, function(a)
+ return extract(read(a)) end))
+
+ print()
+ print(wrap('Fantastic, I found ' .. tostring(#references) ..
+ ' ' .. plural(#references, 'reference',
+ 'references') .. ' in ' .. tostring(#bibliography) ..
+ ' bibliography ' .. plural(#bibliography, 'file',
+ 'files') .. '. Please wait a moment while the ' ..
+ plural(((check == 'all' and 2) or 1), 'report is',
+ 'reports are') .. ' generated.', 74))
+
+ return operations[check](citations, references)
end
--- run the main function
-runMain(arg)
+-- Call and exit
+os.exit(checkcites(arg))
+
+-- EOF
+