# How can I create macros similar to \pnfmt, \pno, \ppno, \nopp for sections, definitions, etc.?

I would like to create macros similar to the biblatex macros \pnfmt, \pno, \ppno, \nopp for working with page numbers in citations, except for other modes of referencing, e.g., sections, definitions, theorems. etc. Thus, I would like to be able to use, e.g., \secfmt, \secno, \secnos, \nosec in a similar fashion for section labels. Perhaps \nosec and similar do not make sense in this context, however, given the default is to recognise a number as a page number.

N.B., I would also like to have commands equivalent to \ppspace for sections, etc.

The definition of \pno and friends can be found in biblatex.sty (ll. 4151-4156 in v3.16).

\pnfmt does not necessarily relate to page/pages, it is defined as using the postnote format. So it does not make sense to replicate it for other pagination type (except for the analogy). Similarly, \nopp tells biblatex not to treat what follows as pages or any other sectioning type (which are implemented using the page infrastructure), so again it need not be replicated for other sectioning types (except if you want the consistency).

It should be noted that the definitions

\protected\def\pno{\bibstring{page}}%
\protected\def\ppno{\bibstring{pages}}%


for \pno and \ppno can be overwritten by pagination/bookpagination values, so \pno may produce "section" as well. If we don't need that for \secno and friends, because they will always produce "section", the definition is simple

\documentclass[british]{article}
\usepackage[T1]{fontenc}
\usepackage{babel}
\usepackage{csquotes}

\usepackage[backend=biber, style=authoryear]{biblatex}

\newrobustcmd*{\secno}{\ERROR}
\newrobustcmd*{\ssecno}{\ERROR}

\makeatletter
\appto\blx@blxinit{%
\protected\def\secno{\bibstring{section}}%
\protected\def\ssecno{\bibstring{sections}}%
}
\makeatother

\begin{filecontents}{\jobname.bib}
@book{elk,
author     = {Anne Elk},
title      = {A Theory on Brontosauruses},
year       = {1972},
publisher  = {Monthy \& Co.},
location   = {London},
pagination = {paragraph},
}
\end{filecontents}

\begin{document}
ipsum \autocite[then see \secno 3]{nussbaum}
dolor \autocite[see \pno~13]{elk} % produces "par" even though we used \pno

\printbibliography
\end{document}


\ppspace is only used by automatic formatting directives, so I don't see the need for \ssecspace in the context of \pno/\secno and \ppno/\ssecno.

• Thanks a lot for the answer. I agree on \nosec, though I would like to have \secfmt for the sake of consistency — what's the best way to do that? As for \ssecspace... I want spaces to be handled in the same way as with \pno/\ppno, i.e., if you write \pno~3 and \ppspace is set to empty, then "p.3" is printed, but if you write \pno3 and \ppspace is set to \addnbspace, then "p. 3" is printed, and so on. How can this be achieved for sections, etc.? Sep 17, 2021 at 17:58
• Also: is there any reason you're doing newrobustcmd* then redefining with \protected\def later? Why not just the former? Sep 18, 2021 at 1:54
• Oh, I see. because the blx@blxinit code doesn't run until later. But then, why bother with blx@blxinit at all, as opposed to simply executing the code then and there? Sep 18, 2021 at 16:31
• @Noldorin \pnfmt is defined as \protected\def\pnfmt{\printtext[postnote]}. You could issue the same definition for \secfmt but crucially this would not (generally) result in the section bibstring being used. \pnfmt actually stands for "postnote format", so this command responds to the pagination field, which usually means you get "pages", but absolutely need not. You could dip deep into internals and try \newrobustcmd*{\secfmt}{\begingroup\blx@mkpageprefix{section}[\mknormrange]} which fixes the standard postnote format, but forces section pagination. ... Sep 20, 2021 at 7:30
• @Noldorin As for \ppspace have a look at gist.github.com/moewew/fc6b4f38bf6b6102cbe27eba0e1b4360 and observe that \ppspace is only used when biblatex formats everything on its own. As soon as you go in with \pno, you are responsible for the spacing. Sep 20, 2021 at 7:33

In case anyone is curious, this is my solution, based on @moewe's answer to a large extent.

I ended up incorporating analogues of \ppspace to be consistency. It's nice to control spacing this way and always ignore the whitespace (including non-breaking space) between, e.g., \secno and 3 in \secno~3 or \secno 3.

Update: Based on @moewe's comments, I'll probably remove the analogues of \ppspace after all.

% Define command for gobbling whitespace chars (including final non-breaking space).
\NewDocumentCommand \gobblespaces {} {
\exp_last_unbraced:NV \peek_charcode_remove_ignore_spaces:NT \c_tilde_str {}
}

% ---- Define various bibliographic strings.

\NewBibliographyString{section}
\NewBibliographyString{sections}
\NewBibliographyString{chapter}
\NewBibliographyString{chapters}
\NewBibliographyString{figure}
\NewBibliographyString{figures}
\NewBibliographyString{footnote}
\NewBibliographyString{footnotes}
\NewBibliographyString{definition}
\NewBibliographyString{definitions}
\NewBibliographyString{proposition}
\NewBibliographyString{propositions}
\NewBibliographyString{lemma}
\NewBibliographyString{lemmas}
\NewBibliographyString{theorem}
\NewBibliographyString{theorems}

\DefineBibliographyStrings{english}{
section = {\S},
sections = {\S\S},
chapter = {ch.},
chapters = {chs.},
figure = {fig.},
figures = {figs.},
footnote = {fn.},
footnotes = {fns.},
definition = {dfn.},
definitions = {dfns.},
proposition = {prop.},
propositions = {props.},
lemma = {lem.},
lemmas = {lems.},
theorem = {thm.},
theorems = {thms.},
}

% ----

% ---- Define commands for citing various textual elements.

\NewDocumentCommand \gen_ref_cmds { m } {
\tl_map_inline:nn { #1 } {
\seq_set_split:Nnn \item_seq { } { ##1 }
\seq_pop:NN \item_seq \x
\seq_pop:NN \item_seq \bibstring_singular_key
\seq_pop:NN \item_seq \bibstring_plural_key

\StrLeft{\x}{1}[\x_first_char]
\exp_args:NNc \tl_set:Nn \xxspace { \x_first_char \x space }
\exp_args:NNc \tl_set:Nn \xno { \x no }
\exp_args:NNc \tl_set:Nn \xxno { \x_first_char \x no }

\exp_args:NV \NewDocumentCommand \xxspace {} {
}
\exp_args:NV \NewDocumentCommand \xno {} { \ERROR }
\exp_args:NV \NewDocumentCommand \xxno {} { \ERROR }

\exp_args:NNe \appto \blx@blxinit {
\RenewDocumentCommand \xno {} {
\exp_not:N \bibstring {\bibstring_singular_key}
\xxspace
\exp_not:N \gobblespaces
}
\RenewDocumentCommand \xxno {} {
\exp_not:N \bibstring {\bibstring_plural_key}
\xxspace
\exp_not:N \gobblespaces
}
}
}
}

\gen_ref_cmds {
{ {sec} {section} {sections} }
{ {ch} {chapter} {chapters} }
{ {fig} {figure} {figures} }
{ {fn} {footnote} {footnotes} }
% { {eq} {equation} {equations} }
{ {dfn} {definition} {definitions} }
{ {prop} {proposition} {propositions} }
{ {lem} {lemma} {lemmas} }
{ {thm} {theorem} {theorems} }
}

% ----

% ---- Configure spaces within citations.

\RenewDocumentCommand \ssecspace {} {}
\RenewDocumentCommand \ppspace {} { \addnbspace }

% ----