%% Manual for inspirehep.sty.  Build with:  make doc
%%
%% Every example is executed as it is shown: each demo is written to a file by
%% fancyvrb's VerbatimOut, then both \VerbatimInput (what you see) and \input
%% (what runs).  The output printed under an example therefore cannot drift
%% from the code above it.  The data is pinned in inspirehep-doc-data.tex,
%% which `make doc' refreshes.
\documentclass[a4paper,11pt]{article}
\usepackage[T1]{fontenc}
\usepackage[margin=1.1in]{geometry}
\usepackage[hidelinks]{hyperref}
\usepackage{booktabs}
\usepackage{fancyvrb}
\usepackage{xcolor}
\usepackage[plots, data=inspirehep-doc-data, fetch=off]{inspirehep}

%% ---------------------------------------------------------------------------
%% Demo machinery
\definecolor{demoframe}{gray}{0.72}
\definecolor{demoground}{gray}{0.97}
% The whole pair -- code and its output -- is boxed together so a page break
% can never separate what you write from what you get.
\newenvironment{demo}
  {\VerbatimEnvironment\begin{VerbatimOut}{\jobname-demo.vrb}}
  {\end{VerbatimOut}\par\medskip\noindent
   \begin{minipage}{\linewidth}
   \VerbatimInput[frame=single, rulecolor=\color{demoframe}, fontsize=\small,
     label={\normalfont\scriptsize\textcolor{black!55}{you write}}]{\jobname-demo.vrb}%
   \vspace{-0.9\baselineskip}\noindent
   {\setlength{\fboxsep}{7pt}\setlength{\fboxrule}{0.4pt}%
    \fcolorbox{demoframe}{demoground}{%
      \begin{minipage}{\dimexpr\linewidth-2\fboxsep-2\fboxrule\relax}
        {\scriptsize\textcolor{black!55}{you get}\par\smallskip}%
        \input{\jobname-demo.vrb}
      \end{minipage}}}%
   \end{minipage}\medskip\par}
\DefineVerbatimEnvironment{code}{Verbatim}
  {frame=single, rulecolor=\color{demoframe}, fontsize=\small}

\newcommand{\pkg}[1]{\textsf{#1}}
\newcommand{\opt}[1]{\texttt{#1}}
\providecommand{\BibTeX}{B\textsc{ib}\TeX}
\ExplSyntaxOn
\NewDocumentCommand \datadate {} { \tl_use:N \g_inspirehep_fetched_tl }
\ExplSyntaxOff
\setlength{\parindent}{0pt}
\setlength{\parskip}{0.55em}

\title{The \pkg{inspirehep} package\\[0.3em]
  \large Live INSPIRE-HEP citation counts, references, and plots}
\author{Lawrence Lee\\
  \small\url{https://github.com/lawrenceleejr/inspirehep-latex}}
\date{Version 0.2\quad 2026/08/29}

\begin{document}
\maketitle

\begin{abstract}
\noindent
\pkg{inspirehep} puts live data from \href{https://inspirehep.net}{INSPIRE-HEP}
into a \LaTeX{} document. Hand a command a paper's id and it typesets the
title, the citation count, the full reference, or a plot of its citations over
time; hand it a person's id and it gives their paper count, citation count,
$h$-index, or either as a plot. The numbers live in a generated file, so the
document itself always compiles --- offline, on a stranger's machine, on
Overleaf.

\smallskip
Every example below is executed exactly as shown; the grey panels are this
manual's real output, from data fetched on \datadate.
\end{abstract}

\section{Quick start}

Put \texttt{inspirehep.sty} next to your document (or anywhere on
\texttt{TEXINPUTS}) and write:

\begin{code}
\documentclass{article}
\usepackage[hidelinks]{hyperref}
\usepackage{inspirehep}
\begin{document}
Our review \inspirepub{1701002} has aged well.

I have written \inspirepapers{1071846} papers, cited
\inspirecitations[round=1000]{1071846} times.
\end{document}
\end{code}

Then either compile with shell escape and let the package fetch for itself,

\begin{code}
pdflatex -shell-escape cv.tex    % fetches, writes inspirehep-data.tex
pdflatex -shell-escape cv.tex    % the numbers appear
\end{code}

or run the bundled helper once and compile normally:

\begin{code}
python3 inspirehep-fetch.py cv.tex
pdflatex cv.tex
\end{code}

Either way the body renders as:

\begin{demo}
Our review \inspirepub{1701002} has aged well.

I have written \inspirepapers{1071846} papers, cited
\inspirecitations[round=1000]{1071846} times.
\end{demo}

Two passes the first time, exactly like a cross-reference. After that the
package only refetches when there is a reason: a record you have just added,
or data older than \opt{maxage} days.

\section{Where the numbers come from}

Both fetchers write the same generated file, \texttt{inspirehep-data.tex}: a
flat list of declarations the package reads at \verb|\begin{document}|.

\begin{code}
%% GENERATED by inspirehep-fetch.py -- do not edit.
\inspiresetcites{1701002}{245}
\inspiresettitle{1701002}{Collider Searches for Long-Lived ...}
\inspiresetkey{1701002}{Lee:2018pag}
\inspiresetref{1701002}{L.~Lee, C.~Ohm, A.~Soffer and ...}
\inspiresetyears{2642414}{(2019,1) (2021,2) (2022,6) ...}
\inspiresetauthorstat{1071846}{citations}{207838}
\inspiresetfetched{2026-08-29}{739767}
\end{code}

Commit this file. Anyone --- including Overleaf, including you offline ---
then compiles your document with correct numbers and no tooling at all. When
the data is older than \opt{maxage} days, every compile says so:

\begin{code}
Package inspirehep Warning: The data dates from 2026-08-29 (about 130
(inspirehep)                days ago).
(inspirehep)                Refresh with -shell-escape or inspirehep-fetch.py
\end{code}

The build still succeeds; the warning is a reminder, not an error.

\paragraph{What each side needs.}
The self-fetch needs unrestricted shell escape \emph{and} \texttt{python3} on
the path --- it delegates the network work to the helper, so there is exactly
one implementation of the API handling. The helper alone needs only
\texttt{python3}; it reads your sources to find every id you use, so in the
common case it takes no arguments. Neither is needed to \emph{typeset}.

\paragraph{Multi-file documents.}
Point either fetcher at the main file and it follows \verb|\input|,
\verb|\include|, and \verb|\subfile| from there, however deeply nested:

\begin{code}
python3 inspirehep-fetch.py main.tex
  Scanning 4 file(s): 3 record(s), 0 plot(s), 0 citation(s), 1 author(s)
\end{code}

Names resolve the way \LaTeX{} resolves them --- relative to the main
document's directory --- and then, failing that, relative to the file doing the
including, which is what \pkg{subfiles} and \pkg{import} do. A file that
cannot be found is skipped (it may be generated, or inside a conditional), and
a cycle of \verb|\input|s terminates rather than looping. Pass
\opt{-{}-no-follow} to scan only the files you name.

\paragraph{Overleaf.}
Overleaf disables shell escape and its compile servers have no network, so
nothing can fetch \emph{there} --- but your document still typesets correct
numbers, because they are just an \verb|\input| file. To keep them current
from inside Overleaf:

\begin{enumerate}
  \item Upload \texttt{inspirehep.sty} to the project.
  \item Add \texttt{inspirehep-data.tex} with \emph{New file $\to$ From
    external URL}, pointing at the raw copy in your repository (kept fresh by
    CI or your local builds).
  \item Overleaf gives linked files a \emph{Refresh} button: new numbers are
    one click, no recompile tricks.
\end{enumerate}

Overleaf's Git sync does not fetch submodules, so include the \texttt{.sty}
as a plain file there.

\section{Papers}

A record can be named two ways, and every command takes either --- they are
told apart by shape, so nothing has to be declared:

\begin{center}\small
\begin{tabular}{@{}lll@{}}
\toprule
& Looks like & Where to find it \\
\midrule
recid  & \texttt{2642414}          & the number in the record's URL,
                                     \texttt{inspirehep.net/literature/}\textbf{\texttt{2642414}} \\
texkey & \texttt{Accettura:2023ked} & the \BibTeX{} key INSPIRE assigns \\
\bottomrule
\end{tabular}
\end{center}

\begin{demo}
by recid:  \inspirepub[cites=false]{1701002}

by texkey: \inspirepub[cites=false]{Lee:2018pag}
\end{demo}

Both link to the record by number, so a texkey costs nothing. A record with
more than one texkey answers to any of them.

\subsection{\texttt{\textbackslash inspirepub}: one command, options for what it shows}

\begin{demo}
\inspirepub{2642414}
\end{demo}

The title came from INSPIRE, linked to the record, with the live citation
count. Each piece is an option:

\begin{demo}
\inspirepub[year]{1701002}
\end{demo}

\begin{demo}
\inspirepub[cites=false]{2642414}
\end{demo}

\begin{demo}
\inspirepub[link=false, cites=false]{2642414}
\end{demo}

Prefer your own wording? Your title, INSPIRE's count:

\begin{demo}
\inspirepub[title={A muon collider design study}]{2642414}
\end{demo}

And \opt{ref} swaps the title for the full reference, exactly as INSPIRE
formats it (see the next subsection):

\begin{demo}
\inspirepub[ref, cites=false]{1701002}
\end{demo}

\subsection{The pieces, separately}

Everything \verb|\inspirepub| assembles is also a command of its own, for
building your own layout:

\begin{demo}
\begin{tabular}{@{}ll@{}}
  title & \inspiretitle{2642414}       \\
  count & \inspirecites{2642414}       \\
  year  & \inspireyear{2642414}        \\
  key   & \texttt{\inspirekey{2642414}}
\end{tabular}
\end{demo}

\subsection{References}

\verb|\inspireref| gives the reference as INSPIRE itself renders it ---
authors, journal, errata, DOI, arXiv number --- so it matches what everyone
else in the field cites, and there is no author-list or journal-abbreviation
logic in this package to get wrong.

\begin{demo}
\inspireref[cites=false]{1701002}
\end{demo}

By default it, too, carries the count (\opt{cites=false} above turned it off).

INSPIRE records errata, which a CV usually does not want, so they are off by
default. \opt{errata} puts them back:

\begin{demo}
\inspireref[cites=false, errata]{1701002}
\end{demo}

A collaboration paper is credited by INSPIRE to its first author and
\emph{et al.}; \opt{collab} credits the collaboration instead, which is the
usual convention in a publication list:

\begin{demo}
\inspireref[cites=false]{1298030}
\end{demo}

\begin{demo}
\inspireref[cites=false, collab]{1298030}
\end{demo}

The wording is \verb|\inspirecollabformat|, so
\verb|\renewcommand{\inspirecollabformat}[1]{#1}| gives a bare
``ATLAS''. Both options work per call or document-wide --- the reference is
stored in its parts and assembled as it is typeset, so switching either one
never means refetching.

The \opt{style} option picks INSPIRE's European numbering (\opt{latex-eu}, the
default: volume (year) page) or American (\opt{latex-us}: volume, page (year));
that one does apply at fetch time, so set it as a package option.

\subsection{A \texttt{.bib} file you never write}

\verb|\inspirecite{<id>}| is \verb|\cite| by INSPIRE id. The fetcher collects
INSPIRE's own \BibTeX{} entry --- verbatim, from
\texttt{?format=bibtex} --- for every id you cite, into
\texttt{inspirehep-refs.bib}:

\begin{code}
\usepackage{inspirehep}
...
as shown in \inspirecite{1701002}, ...
...
\bibliographystyle{unsrt}
\bibliography{inspirehep-refs}
\end{code}

The generated file begins:

\begin{code}
%% GENERATED by inspirehep-fetch.py -- do not edit.
@article{Lee:2018pag,
    author = "Lee, Lawrence and Ohm, Christian and Soffer, Abner and
              Yu, Tien-Tien",
    title = "{Collider Searches for Long-Lived Particles Beyond the
              Standard Model}",
    ...
\end{code}

You never handle a \BibTeX{} key yourself --- though \verb|\inspirekey{<id>}|
hands it to you if you want it (it is
\texttt{\inspirekey{1701002}} here), so \verb|\inspirecite| composes with
everything that expects \verb|\cite|.

\verb|\inspirecite| takes a texkey too, which is the one case where it works
before anything has ever been fetched: a texkey \emph{is} the citation key, so
\verb|\inspirecite{Lee:2018pag}| is simply \verb|\cite{Lee:2018pag}|. The
entry still has to reach your \texttt{.bib}, so a fetch is still what puts it
there.

\section{People}

The id is the number in a profile URL,
\texttt{inspirehep.net/authors/}\textbf{\texttt{1071846}}, or a BAI such as
\texttt{J.Smith.1}. Every command takes the id it is asking about --- there is
deliberately no package-wide author --- so one document can discuss several
people:

\begin{demo}
\begin{tabular}{@{}lrrr@{}}
            & papers & citations & $h$ \\
  L.~Lee    & \inspirepapers{1071846}
            & \inspirecitations{1071846}
            & \inspirehindex{1071846} \\
  T.~Holmes & \inspirepapers{1067690}
            & \inspirecitations{1067690}
            & \inspirehindex{1067690}
\end{tabular}
\end{demo}

\subsection{Round numbers that stay true}

A summary line usually wants ``over $N$'', and the rounding must go
\emph{down}: rounded up, the claim is false the moment it is typeset.
\opt{round=} rounds any figure down to a multiple of its value:

\begin{demo}
Over \inspirepapers[round=100]{1071846} papers, with over
\inspirecitations[round=1000]{1071846} citations and an
$h$-index of \inspirehindex{1071846}.
\end{demo}

\verb|\inspireauthorstat{<id>}{<key>}| is the general form behind all three,
with \opt{<key>} one of \opt{papers}, \opt{citations}, \opt{hindex}:

\begin{demo}
\inspireauthorstat[round=1000]{1071846}{citations}
\end{demo}

\section{Plots}

Load the package with the \opt{plots} option (it pulls in \pkg{pgfplots},
which is why it is opt-in --- a CV that never plots should not pay for
Ti\emph{k}Z). \verb|\inspireplot{<id>}| is the citation history of one paper:

\begin{demo}
\inspireplot{2642414}
\end{demo}

\verb|\inspireauthorplot{<id>}{papers}| or \verb|{citations}| is a person's
output or impact over time:

\begin{demo}
\inspireauthorplot{1071846}{papers}
\end{demo}

The default style is deliberately spare: one line, axis lines only where they
carry information, no grid, box, marks, or legend. Three hooks change it ---
\verb|\inspireplotwidth|, \verb|\inspireplotheight|, and
\verb|\inspireplotstyle|, which takes any \pkg{pgfplots} axis keys:

\begin{demo}
{\renewcommand{\inspireplotwidth}{0.6\linewidth}%
 \renewcommand{\inspireplotheight}{3cm}%
 \renewcommand{\inspireplotstyle}{ymajorgrids,
   every axis plot/.append style={red!60!black}}%
 \inspireauthorplot{1071846}{citations}}
\end{demo}

Braces confine the change to one plot; at the top level it holds for all of
them.

\section{Numbers and separators}

Figures are digit-grouped with a comma by default. \opt{sep=} chooses another
convention, per call or document-wide, and \opt{sepstring=} takes anything
else:

\begin{demo}
\begin{tabular}{@{}ll@{}}
  \texttt{sep=comma}      & \inspirecitations{1071846} \\
  \texttt{sep=period}     & \inspirecitations[sep=period]{1071846} \\
  \texttt{sep=space}      & \inspirecitations[sep=space]{1071846} \\
  \texttt{sep=thin}       & \inspirecitations[sep=thin]{1071846} \\
  \texttt{sep=underscore} & \inspirecitations[sep=underscore]{1071846} \\
  \texttt{sep=none}       & \inspirecitations[sep=none]{1071846} \\
  \texttt{sepstring='}    & \inspirecitations[sepstring={'}]{1071846}
\end{tabular}
\end{demo}

Set once for the whole document with
\verb|\usepackage[sep=thin]{inspirehep}| or anywhere with
\verb|\inspiresetup{sep=thin}|; either way a per-call option still wins for
that one call, and a change made inside a group ends with the group.

\section{When data is missing}

An id the data file knows nothing about --- brand new, mistyped, or never
fetched --- typesets a visible marker rather than something silently wrong,
and flags itself so the next fetch asks about it:

\begin{demo}
\inspirepub{999999999}
\end{demo}

Fresh papers deserve better than advertising a zero: counts below
\opt{mincites} (default 1) print nothing at all.

\begin{demo}
before\inspirecites{999999999}after
  ({\inspiresetup{mincites=1000}%
    also nothing: 152 < 1000\inspirecites{1298030}})
\end{demo}

Fallback values can be declared in the document, used only until the real
figures arrive --- handy for a repository's first ever build, and they never
override fetched data:

\begin{demo}
\inspiredefaultauthorstat{20000000}{papers}{42}
\inspiredefaultauthorstat{1071846}{papers}{9}
never fetched: \inspirepapers{20000000};
fetched wins: \inspirepapers{1071846}
\end{demo}

\verb|\inspiredefaultstat{<key>}{<n>}| does the same for the single person
named by the helper's \opt{--author}, who needs no id at the call site.

\section{Options}

Every option is both a package option and (where it makes sense per call) an
optional argument; \verb|\inspiresetup{...}| changes any of them
mid-document.

\begin{center}\small
\begin{tabular}{@{}llp{7.2cm}@{}}
\toprule
Option & Default & Meaning \\
\midrule
\opt{cites}     & \opt{true}  & show the citation count \\
\opt{ref}       & \opt{false} & full reference instead of the title \\
\opt{year}      & \opt{false} & append the publication year \\
\opt{errata}    & \opt{false} & include any erratum in a reference \\
\opt{collab}    & \opt{false} & credit a collaboration paper to the
                                collaboration rather than to its first author \\
\opt{link}      & \opt{true}  & hyperlink the title (needs \pkg{hyperref};
                                plain text without it) \\
\opt{title}     & ---         & override the fetched title \\
\opt{round}     & \opt{1}     & round a figure \emph{down} to a multiple of this \\
\opt{mincites}  & \opt{1}     & counts below this print nothing \\
\opt{sep}       & \opt{comma} & \opt{comma}, \opt{period}, \opt{space},
                                \opt{thin}, \opt{underscore}, \opt{none} \\
\opt{sepstring} & ---         & any other separator text \\
\opt{plots}     & \opt{false} & load \pkg{pgfplots} for the plotting commands \\
\opt{style}     & \opt{latex-eu} & reference format, \opt{latex-eu} or
                                   \opt{latex-us} (applies at fetch time) \\
\opt{data}      & \opt{inspirehep-data} & basename of the generated data file \\
\opt{bib}       & \opt{inspirehep-refs} & basename of the generated \texttt{.bib} \\
\opt{script}    & \opt{inspirehep-fetch.py} & where the self-fetch finds the
                                              helper (a submodule path, say) \\
\opt{maxage}    & \opt{120}   & days before the data is called stale \\
\opt{fetch}     & \opt{auto}  & \opt{auto}, \opt{on} (warn if impossible),
                                \opt{off} \\
\bottomrule
\end{tabular}
\end{center}

\section{House style}

Five hooks control how things are set; redefine any of them:

\begin{demo}
{\renewcommand{\inspiretitleformat}[1]{\textsc{#1}}%
 \renewcommand{\inspirecitestext}[1]{cited #1 times}%
 \renewcommand{\inspirecitesformat}[1]{ --- \emph{#1}}%
 \inspirepub{1298030}}
\end{demo}

\begin{code}
\renewcommand{\inspiretitleformat}[1]{\textbf{#1}}   % around the title
\renewcommand{\inspirecitestext}[1]{#1~citations}    % the words
\renewcommand{\inspirecitesformat}[1]{~{\small[#1]}} % attaching them
\renewcommand{\inspireyearformat}[1]{~(#1)}          % the year
\renewcommand{\inspirenumformat}[1]{...}             % digit grouping itself
\renewcommand{\inspirenumsep}{\,}                    % what goes between groups
\renewcommand{\inspirecollabformat}[1]{#1~Collab.}   % `collab' wording
\renewcommand{\inspiremissing}[1]{\textbf{[?~#1]}}   % the missing-data marker
\end{code}

\verb|\inspirenumsep| is the separator on its own, for a character the
\opt{sep} option does not offer; \verb|\inspiremissing| is what an unknown id
typesets --- the next section describes when, and this is how to restyle it.

A CV-flavoured example --- the count as quiet grey metadata:

\begin{demo}
{\renewcommand{\inspirecitesformat}[1]{%
   \nobreakspace{\small\textcolor{black!45}{[#1]}}}%
 \inspirepub{2642414}}
\end{demo}

\section{The data file, for the curious}

The declarations a fetcher writes are ordinary commands, so you can also set
or patch anything by hand --- useful for records INSPIRE does not have:

\begin{center}\small
\begin{tabular}{@{}ll@{}}
\toprule
\verb|\inspiresetcites{<id>}{<n>}|            & a record's citation count \\
\verb|\inspiresettitle{<id>}{<title>}|        & its title \\
\verb|\inspiresetkey{<id>}{<key>}|            & its \BibTeX{} key \\
\verb|\inspiresetrecid{<id>}{<recid>}|        & the record number behind a
                                                texkey, so links still work \\
\verb|\inspiresetrefauthors{<id>}{...}|       & its author list \\
\verb|\inspiresetrefcollab{<id>}{ATLAS}|      & its collaboration, if any \\
\verb|\inspiresetrefpub{<id>}{...}|          & journal, DOI, arXiv number \\
\verb|\inspiresetreferrata{<id>}{...}|       & any erratum \\
\verb|\inspiresetref{<id>}{<reference>}|     & a whole reference, overriding
                                               the four above \\
\verb|\inspiresetyears{<id>}{(y,n) (y,n) ...}|& its citations per year \\
\verb|\inspiresetauthorstat{<id>}{<key>}{<n>}|& a person's figure \\
\verb|\inspiresetstat{<key>}{<n>}|            & the same, for the one person
                                                named by \opt{--author} \\
\verb|\inspiresetauthoryears{<id>}{<kind>}{...}| & a person's series \\
\verb|\inspiresetfetched{<date>}{<dayno>}|    & when it was all fetched \\
\bottomrule
\end{tabular}
\end{center}

\section{Requirements and limits}

Typesetting needs a current \LaTeX{} (\pkg{xparse} and \pkg{l3keys2e} from the
kernel), plus \pkg{pgfplots} if and only if you pass \opt{plots}. Refreshing
the data needs \texttt{python3} (standard library only); the self-fetch
additionally needs unrestricted shell escape. Counts are whatever INSPIRE
reports, self-citations included. A texkey given to \verb|\inspirecite| is
used as-is when nothing has been fetched yet; every other command needs the
data file either way.

\section{Licence}

LPPL 1.3c or later; maintained by Lawrence Lee. Issues and contributions:
\url{https://github.com/lawrenceleejr/inspirehep-latex}.

\end{document}
