diff options
author | Karl Berry <karl@freefriends.org> | 2012-03-12 23:40:01 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2012-03-12 23:40:01 +0000 |
commit | 09da414d5ff0230b79f8a5f7edcaa05f81e83adb (patch) | |
tree | e08f993f81230a42913b1d82ca43f6d608319d5c /Master | |
parent | 6e97d979159e30694e7dab6f6697f6c6376984fa (diff) |
new lua script checkcites (12mar12)
git-svn-id: svn://tug.org/texlive/trunk@25623 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master')
27 files changed, 1135 insertions, 1 deletions
diff --git a/Master/bin/alpha-linux/checkcites b/Master/bin/alpha-linux/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/alpha-linux/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/amd64-freebsd/checkcites b/Master/bin/amd64-freebsd/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/amd64-freebsd/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/amd64-kfreebsd/checkcites b/Master/bin/amd64-kfreebsd/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/amd64-kfreebsd/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/i386-cygwin/checkcites b/Master/bin/i386-cygwin/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/i386-cygwin/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/i386-freebsd/checkcites b/Master/bin/i386-freebsd/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/i386-freebsd/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/i386-kfreebsd/checkcites b/Master/bin/i386-kfreebsd/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/i386-kfreebsd/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/i386-linux/checkcites b/Master/bin/i386-linux/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/i386-linux/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/i386-netbsd/checkcites b/Master/bin/i386-netbsd/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/i386-netbsd/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/i386-solaris/checkcites b/Master/bin/i386-solaris/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/i386-solaris/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/mips-irix/checkcites b/Master/bin/mips-irix/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/mips-irix/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/powerpc-aix/checkcites b/Master/bin/powerpc-aix/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/powerpc-aix/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/powerpc-linux/checkcites b/Master/bin/powerpc-linux/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/powerpc-linux/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/sparc-linux/checkcites b/Master/bin/sparc-linux/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/sparc-linux/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/sparc-solaris/checkcites b/Master/bin/sparc-solaris/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/sparc-solaris/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/universal-darwin/checkcites b/Master/bin/universal-darwin/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/universal-darwin/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/win32/checkcites.exe b/Master/bin/win32/checkcites.exe Binary files differnew file mode 100755 index 00000000000..5777d90a17a --- /dev/null +++ b/Master/bin/win32/checkcites.exe diff --git a/Master/bin/x86_64-darwin/checkcites b/Master/bin/x86_64-darwin/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/x86_64-darwin/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/x86_64-linux/checkcites b/Master/bin/x86_64-linux/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/x86_64-linux/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/bin/x86_64-solaris/checkcites b/Master/bin/x86_64-solaris/checkcites new file mode 120000 index 00000000000..3ca58361609 --- /dev/null +++ b/Master/bin/x86_64-solaris/checkcites @@ -0,0 +1 @@ +../../texmf-dist/scripts/checkcites/checkcites.lua
\ No newline at end of file diff --git a/Master/texmf-dist/doc/support/checkcites/README b/Master/texmf-dist/doc/support/checkcites/README new file mode 100644 index 00000000000..37a2b00d74c --- /dev/null +++ b/Master/texmf-dist/doc/support/checkcites/README @@ -0,0 +1,101 @@ +checkcites.lua -- Version 1.0g from March 7, 2012. +================================================== + +License +------- + +Copyright 2012 Enrico Gregorio, Paulo Roberto Massa Cereda + +- Enrico dot Gregorio at univr dot it +- cereda at users dot sf dot net + +This script is licensed under the LaTeX Project Public License. +If you want to support LaTeX development by a donation, the best +way to do this is donating to the TeX Users Group. + +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. + +Installation +------------ + +1. Create a new directory named 'checkcites' inside the 'scripts' + directory of your TEXMF tree and copy the 'checkcites.lua' inside + the new directory. In TeX Live, the new directory would be: + + texlive/<year>/texmf/scripts/checkcites + +2. Rebuild the filename databases with the proper distro tool, + e.g, running 'mktexlsr'. + +3. Create a symbolic link to the newly created script inside + the 'bin' directory of your TeX distro. In TeX Live, the + full path is: + + texlive/<year>/bin/<arch> + + For TeX Live: + + Win32: make a copy of 'runscript.exe' inside the very same + location (i.e, 'bin/win32') and rename it to + 'checkcites.exe'. + + Linux: create a symbolic link (i.e, 'ln -s') inside the 'bin' + directory, targeting the script set in #1. Name it + 'checkcites' and give it proper execute ('x') permission. + +Usage +----- + +The script is pretty simple to use. The only requirement is a recent +TeX distribution, such as TeX Live. Then 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: + +$ checkcites foo.aux + +checkcites allows an additional argument that will tell it how to +behave. For example + +$ checkcites --unused foo.aux + +will make the script only look for unused references in your '.bib' +file. The argument order doesn't matter, you can also run + +$ checkcites foo.aux --unused + +and get the same behaviour. Similarly, you can use + +$ checkcites --undefined foo.aux + +to make the script only look for undefined references in your +'.tex' file. If you want checkcites to look for both unused and +undefined references, go with + +$ checkcites --all foo.aux + +If no special argument is provided, --all is set as default. + +Official code repository +------------------------ + +http://github.com/cereda/checkcites diff --git a/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf Binary files differnew file mode 100644 index 00000000000..c99f2d71d52 --- /dev/null +++ b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.pdf diff --git a/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex new file mode 100644 index 00000000000..e520b1085f0 --- /dev/null +++ b/Master/texmf-dist/doc/support/checkcites/checkcites-doc.tex @@ -0,0 +1,339 @@ +\documentclass[12pt,a4paper]{article} + +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} + +\usepackage[english]{babel} + +\usepackage[margin=1in]{geometry} + +\usepackage[svgnames]{xcolor} +\usepackage[colorlinks, linkcolor={blue}, urlcolor={blue}]{hyperref} + +\usepackage{tcolorbox} +\tcbuselibrary{listings} + +\newcommand{\checkcites}{\texttt{checkcites}} +\newcommand{\email}[1]{\small\texttt{#1}} +\newcommand{\version}{Version 1.0g from March 7, 2012.} + +\newenvironment{infoblock}[1] + {\par\addvspace{\medskipamount} + \begin{tcolorbox}[colframe=DarkTurquoise,coltitle=black,fonttitle=\bfseries,title=#1]} + {\end{tcolorbox}\addvspace{\medskipamount}} + +\newenvironment{terminal} + {\par\addvspace{\medskipamount} + \begin{tcolorbox}[colframe=DarkTurquoise]} + {\end{tcolorbox}\par\addvspace{\medskipamount}} + +\title{The \checkcites\footnote{\version}\ \ script} +\author{% + Enrico Gregorio\\\email{Enrico dot Gregorio at univr dot it}\\[3ex] + Paulo Roberto Massa Cereda\\\email{cereda at users dot sf dot net}% +} +\date{} + +\begin{document} + +\maketitle + +\tableofcontents + +\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. + +\begin{infoblock}{Attention!} +\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} + +\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. + +\begin{infoblock}{Attention!} +If \verb|\citation{*}| is found, the script ends, mainly because all +citations will be used in this case. We opted for ending the script +instead of ignoring this step. +\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. + +\begin{infoblock}{Attention!} +If no \verb|\bibdata| command is found, the script ends. There's +nothing to do in this case. +\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 +\[ +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 +\[ +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. + +\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. + +\begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only, + title=Bibliography file, fonttitle=\bfseries, + listing options={columns=fullflexible,basicstyle=\ttfamily}} +@BOOK{foo:2012a, + title = {My Title One}, + publisher = {My Publisher One}, + year = {2012}, + editor = {My Editor One}, + author = {Author One} +} + +@BOOK{foo:2012b, + title = {My Title Two}, + publisher = {My Publisher Two}, + year = {2012}, + editor = {My Editor Two}, + author = {Author Two} +} + +@BOOK{foo:2012c, + title = {My Title Three}, + publisher = {My Publisher Three}, + year = {2012}, + editor = {My Editor Three}, + author = {Author Three} +} + +@BOOK{foo:2012d, + title = {My Title Four}, + publisher = {My Publisher Four}, + year = {2012}, + editor = {My Editor Four}, + author = {Author Four} +} + +@BOOK{foo:2012e, + title = {My Title Five}, + publisher = {My Publisher Five}, + year = {2012}, + editor = {My Editor Five}, + author = {Author Five} +} +\end{tcblisting} + +The second file is our main \LaTeX{} document, \verb|document.tex|. + +\begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only, + title=Main document, fonttitle=\bfseries, + listing options={columns=fullflexible,basicstyle=\ttfamily}} +\documentclass{article} + +\begin{document} + +Hello world \cite{foo:2012a,foo:2012c}, how are you \cite{foo:2012f}, +and goodbye \cite{foo:2012d,foo:2012a}. + +\bibliographystyle{plain} +\bibliography{example} + +\end{document} +\end{tcblisting} + +Open a terminal and run \verb|checkcites|: + +\begin{terminal} +\begin{verbatim} +$ checkcites +\end{verbatim} +\tcblower +\begin{verbatim} +checkcites.lua -- a reference checker script (v1.0g) +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. +\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: +\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|: +\begin{terminal} +\begin{verbatim} +$ pdflatex document.tex +\end{verbatim} +\end{terminal} + +After running \verb|pdflatex| on our \verb|.tex| file, there's now a +\verb|document.aux| file in our work directory. + +\begin{tcblisting}{colframe=DarkTurquoise,coltitle=black,listing only, + title=Auxiliary file, fonttitle=\bfseries, + listing options={columns=fullflexible,basicstyle=\ttfamily}} +\relax +\citation{foo:2012a} +\citation{foo:2012c} +\citation{foo:2012f} +\citation{foo:2012d} +\citation{foo:2012a} +\bibstyle{plain} +\bibdata{example} +\end{tcblisting} + +Now we can run \checkcites\ on the \verb|document.aux| file: + +\begin{terminal} +\begin{verbatim} +$ checkcites document.aux +\end{verbatim} +\tcblower +\begin{verbatim} +checkcites.lua -- a reference checker script (v1.0g) +Copyright (c) 2012 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). + +Unused reference(s) in your bibliography file(s): 2 +- foo:2012b +- foo:2012e + +Undefined reference(s) in your TeX file: 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|. + +\checkcites\ allows a command line switch that will tell it how to +behave. For example, + +\begin{terminal} +\begin{verbatim} +$ 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 + +\begin{terminal} +\begin{verbatim} +$ checkcites document.aux --unused +\end{verbatim} +\end{terminal} + +The script will behave the same. Similarly, you can use + +\begin{terminal} +\begin{verbatim} +$ 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: + +\begin{terminal} +\begin{verbatim} +$ checkcites --all document.aux +\end{verbatim} +\end{terminal} + +If no special argument is provided, the \verb|--all| flag is set as default. + +\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 +\href{http://www.tug.org/}{TeX Users Group}. + +\begin{infoblock}{Official code repository} +\url{http://github.com/cereda/checkcites} +\end{infoblock} + +\end{document} diff --git a/Master/texmf-dist/scripts/checkcites/checkcites.lua b/Master/texmf-dist/scripts/checkcites/checkcites.lua new file mode 100755 index 00000000000..c2271f28cc4 --- /dev/null +++ b/Master/texmf-dist/scripts/checkcites/checkcites.lua @@ -0,0 +1,673 @@ +#!/usr/bin/env texlua +-- ****************************************************************** +-- checkcites.lua +-- Copyright 2012 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. +-- +-- 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. +-- +-- 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.0g" +DATE = "March 7, 2012" + +-- 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]+" + + end + + local parts = {__index = table.insert} + + setmetatable(parts, parts) + + str:gsub(pattern, parts) + + setmetatable(parts, nil) + + parts.__index = nil + + return parts + +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 + 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 + + 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 + + end + + -- if it's ok to insert + if flag then + + -- insert new element + table.insert(ret, k) + + 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 + + -- show message + print("I found a '*' citation, which means that all references will be used.\nI'm afraid I have nothing to do now.") + + -- and abort the script + os.exit() + + 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 + 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 + else + + -- show message + print("Oh no, I have to check more than one 'bib' file. Please wait.") + + 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 of function +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+{(.+),') 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 + end + + -- remove duplicated references + theReferences = removeDuplicates(theReferences) + + -- print message + print("I found " .. #theReferences .. " reference(s).") + + -- return references + return theReferences + +-- end of function +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 + + end + +-- end of function +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) + + end + + end + +-- end of function +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 + + -- return it as a valid argument + return 4, theArgs[1], nil + + -- end for one parameter + 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 + + end + + else + + -- more than two arguments, return usage code + return 0, nil, nil + + end + +-- end of function +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 +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 +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 +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 +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 +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 + else + + -- 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 + + -- only show unused + showUnusedReferences(a,c) + + -- it's --undefined + else + + -- only show undefined + showUndefinedReferences(a,c) + + end + + -- there's only one parameter, the file name, + -- so we set --all + else + + -- show everything + showUnusedReferences(a,c) + showUndefinedReferences(a,c) + + end + + end + +-- end of function +end + +-- run the main function +runMain(arg) diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index e1af2c2af81..8c7dfe31280 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -83,7 +83,7 @@ my @TLP_working = qw( cd cd-cover cdpbundl cell cellspace censor cfr-lm changebar changelayout changepage changes chappg chapterfolder - chbibref chem-journal + chbibref checkcites chem-journal chemarrow chembst chemcompounds chemcono chemexec chemfig chemmacros chemnum chemstyle cherokee chess chess-problem-diagrams chessboard chessfss chet chextras diff --git a/Master/tlpkg/libexec/ctan2tds b/Master/tlpkg/libexec/ctan2tds index 1d95127cf0b..6a3e8b34529 100755 --- a/Master/tlpkg/libexec/ctan2tds +++ b/Master/tlpkg/libexec/ctan2tds @@ -2085,6 +2085,7 @@ $standardxmt='\.xmt'; 'authorindex' => 'authorindex$', 'bibexport' => 'bibexport\.sh$', 'bundledoc' => '(arlatex|bundledoc)$', + 'checkcites' => '\.lua$', 'ctanify' => '^ctanify$', 'ctanupload' => '\.pl$', 'de-macro' => 'de-macro', diff --git a/Master/tlpkg/tlpsrc/checkcites.tlpsrc b/Master/tlpkg/tlpsrc/checkcites.tlpsrc new file mode 100644 index 00000000000..278a88d5242 --- /dev/null +++ b/Master/tlpkg/tlpsrc/checkcites.tlpsrc @@ -0,0 +1 @@ +binpattern f bin/${ARCH}/checkcites diff --git a/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc b/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc index 2386a18bb5b..46a057b6baa 100644 --- a/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-luatex.tlpsrc @@ -5,6 +5,7 @@ longdesc as an embedded scripting and extension language. http://luatex.org/ # depend collection-basic # +depend checkcites depend interpreter depend lua-visual-debug depend luabibentry |