From d1cb4d61e001c353e99cf0209daeb7e265e350c5 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 24 Nov 2021 21:31:19 +0000 Subject: zref-clever (24nov21) git-svn-id: svn://tug.org/texlive/trunk@61145 c570f23f-e606-0410-a88d-b1316a301751 --- .../texmf-dist/doc/latex/zref-clever/CHANGELOG.md | 8 + .../texmf-dist/doc/latex/zref-clever/DEPENDS.txt | 5 + .../texmf-dist/doc/latex/zref-clever/MANIFEST.md | 350 + Master/texmf-dist/doc/latex/zref-clever/README.md | 22 + .../doc/latex/zref-clever/zref-clever-code.pdf | Bin 0 -> 1035367 bytes .../doc/latex/zref-clever/zref-clever-code.tex | 53 + .../doc/latex/zref-clever/zref-clever.pdf | Bin 0 -> 304271 bytes .../doc/latex/zref-clever/zref-clever.tex | 2163 ++++++ .../source/latex/zref-clever/zref-clever.dtx | 7161 ++++++++++++++++++++ .../source/latex/zref-clever/zref-clever.ins | 99 + .../tex/latex/zref-clever/zref-clever-english.dict | 247 + .../tex/latex/zref-clever/zref-clever-french.dict | 262 + .../tex/latex/zref-clever/zref-clever-german.dict | 502 ++ .../latex/zref-clever/zref-clever-portuguese.dict | 276 + .../tex/latex/zref-clever/zref-clever-spanish.dict | 262 + .../tex/latex/zref-clever/zref-clever.sty | 3519 ++++++++++ Master/tlpkg/bin/tlpkg-ctan-check | 2 +- Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc | 1 + Master/tlpkg/tlpsrc/zref-clever.tlpsrc | 0 19 files changed, 14931 insertions(+), 1 deletion(-) create mode 100644 Master/texmf-dist/doc/latex/zref-clever/CHANGELOG.md create mode 100644 Master/texmf-dist/doc/latex/zref-clever/DEPENDS.txt create mode 100644 Master/texmf-dist/doc/latex/zref-clever/MANIFEST.md create mode 100644 Master/texmf-dist/doc/latex/zref-clever/README.md create mode 100644 Master/texmf-dist/doc/latex/zref-clever/zref-clever-code.pdf create mode 100644 Master/texmf-dist/doc/latex/zref-clever/zref-clever-code.tex create mode 100644 Master/texmf-dist/doc/latex/zref-clever/zref-clever.pdf create mode 100644 Master/texmf-dist/doc/latex/zref-clever/zref-clever.tex create mode 100644 Master/texmf-dist/source/latex/zref-clever/zref-clever.dtx create mode 100644 Master/texmf-dist/source/latex/zref-clever/zref-clever.ins create mode 100644 Master/texmf-dist/tex/latex/zref-clever/zref-clever-english.dict create mode 100644 Master/texmf-dist/tex/latex/zref-clever/zref-clever-french.dict create mode 100644 Master/texmf-dist/tex/latex/zref-clever/zref-clever-german.dict create mode 100644 Master/texmf-dist/tex/latex/zref-clever/zref-clever-portuguese.dict create mode 100644 Master/texmf-dist/tex/latex/zref-clever/zref-clever-spanish.dict create mode 100644 Master/texmf-dist/tex/latex/zref-clever/zref-clever.sty create mode 100644 Master/tlpkg/tlpsrc/zref-clever.tlpsrc (limited to 'Master') diff --git a/Master/texmf-dist/doc/latex/zref-clever/CHANGELOG.md b/Master/texmf-dist/doc/latex/zref-clever/CHANGELOG.md new file mode 100644 index 00000000000..dc8ce5a3ebc --- /dev/null +++ b/Master/texmf-dist/doc/latex/zref-clever/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +## [Unreleased](https://github.com/gusbrs/zref-clever/compare/v0.1.0-alpha...HEAD) + +## [v0.1.0-alpha] + +### Added +- Initial release. diff --git a/Master/texmf-dist/doc/latex/zref-clever/DEPENDS.txt b/Master/texmf-dist/doc/latex/zref-clever/DEPENDS.txt new file mode 100644 index 00000000000..4b47b749558 --- /dev/null +++ b/Master/texmf-dist/doc/latex/zref-clever/DEPENDS.txt @@ -0,0 +1,5 @@ +hard zref +hard l3packages +hard oberdiek +soft hyperref +soft zref-check diff --git a/Master/texmf-dist/doc/latex/zref-clever/MANIFEST.md b/Master/texmf-dist/doc/latex/zref-clever/MANIFEST.md new file mode 100644 index 00000000000..98f72887da7 --- /dev/null +++ b/Master/texmf-dist/doc/latex/zref-clever/MANIFEST.md @@ -0,0 +1,350 @@ +# Manifest for zref-clever + +This file is a listing of all files considered to be part of this package. +It is automatically generated with `texlua build.lua manifest`. + + +## Repository manifest + +The following groups list the files included in the development repository of the package. +Files listed with a ‘†’ marker are included in the TDS but not CTAN files, and files listed +with ‘‡’ are included in both. + +### Source files + +These are source files for a number of purposes, including the `unpack` process which +generates the installation files of the package. Additional files included here will also +be installed for processing such as testing. + +* zref-clever.dtx ‡ +* zref-clever.ins ‡ + +### Typeset documentation source files + +These files are typeset using LaTeX to produce the PDF documentation for the package. + +* zref-clever-code.tex ‡ +* zref-clever.tex ‡ + +### Text files + +Plain text files included as documentation or metadata. + +* CHANGELOG.md ‡ +* MANIFEST.md ‡ +* README.md ‡ +* readme-ctan.md +* DEPENDS.txt ‡ + +### Derived files + +The files created by ‘unpacking’ the package sources. This typically includes +`.sty` and `.cls` files created from DocStrip `.dtx` files. + +* zref-clever.sty † +* zref-clever-english.dict † +* zref-clever-french.dict † +* zref-clever-german.dict † +* zref-clever-portuguese.dict † +* zref-clever-spanish.dict † + +### Typeset documents + +The output files (PDF, essentially) from typesetting the various source, demo, +etc., package files. + +* zref-clever-code.pdf ‡ +* zref-clever.pdf ‡ + +### Test files + +These files form the test suite for the package. `.lvt` or `.lte` files are the individual +unit tests, and `.tlg` are the stored output for ensuring changes to the package produce +the same output. These output files are sometimes shared and sometime specific for +different engines (pdfTeX, XeTeX, LuaTeX, etc.). + +* zc-LanguageSetup01.lvt +* zc-RefTypeSetup01.lvt +* zc-class-article01.lvt +* zc-class-book01.lvt +* zc-class-memoir01.lvt +* zc-class-report01.lvt +* zc-class-scrartcl01.lvt +* zc-class-scrbook01.lvt +* zc-class-scrreprt01.lvt +* zc-compat-amsmath01.lvt +* zc-compat-appendices01.lvt +* zc-compat-appendix01.lvt +* zc-compat-breqn01.lvt +* zc-compat-enumitem01.lvt +* zc-compat-koma-script01.lvt +* zc-compat-listings01.lvt +* zc-compat-memoir01.lvt +* zc-compat-subcaption01.lvt +* zc-compat-subfig01.lvt +* zc-dictionaries01.lvt +* zc-dictionaries02.lvt +* zc-howto-amsmath01.lvt +* zc-howto-enumitem01.lvt +* zc-howto-listings01.lvt +* zc-howto-newfloat01.lvt +* zc-howto-newfloat02.lvt +* zc-howto-newfloat03.lvt +* zc-howto-newfloat04.lvt +* zc-howto-newfloat05.lvt +* zc-howto-newtheorem01.lvt +* zc-howto-newtheorem02.lvt +* zc-howto-newtheorem03.lvt +* zc-howto-newtheorem04.lvt +* zc-howto-zref-xr01.lvt +* zc-label-options01.lvt +* zc-languages01.lvt +* zc-opt-check01.lvt +* zc-opt-d01.lvt +* zc-opt-g01.lvt +* zc-opt-hyperref01.lvt +* zc-opt-hyperref02.lvt +* zc-opt-hyperref03.lvt +* zc-opt-hyperref04.lvt +* zc-opt-hyperref05.lvt +* zc-opt-lang01.lvt +* zc-opt-lang02.lvt +* zc-opt-lang03.lvt +* zc-opt-lang04.lvt +* zc-opt-lang05.lvt +* zc-opt-lang06.lvt +* zc-opt-nocompat01.lvt +* zc-opt-nocompat02.lvt +* zc-opt-nocompat03.lvt +* zc-opt-ref01.lvt +* zc-opt-ref02.lvt +* zc-opt-titleref01.lvt +* zc-precedence-rules01.lvt +* zc-sort01.lvt +* zc-typeset01.lvt +* zc-workaround-breqn01.lvt +* zc-zcref-options01.lvt +* zc-LanguageSetup01.luatex.tlg +* zc-LanguageSetup01.tlg +* zc-LanguageSetup01.xetex.tlg +* zc-RefTypeSetup01.luatex.tlg +* zc-RefTypeSetup01.tlg +* zc-RefTypeSetup01.xetex.tlg +* zc-class-article01.luatex.tlg +* zc-class-article01.tlg +* zc-class-article01.xetex.tlg +* zc-class-book01.luatex.tlg +* zc-class-book01.tlg +* zc-class-book01.xetex.tlg +* zc-class-memoir01.luatex.tlg +* zc-class-memoir01.tlg +* zc-class-memoir01.xetex.tlg +* zc-class-report01.luatex.tlg +* zc-class-report01.tlg +* zc-class-report01.xetex.tlg +* zc-class-scrartcl01.luatex.tlg +* zc-class-scrartcl01.tlg +* zc-class-scrartcl01.xetex.tlg +* zc-class-scrbook01.luatex.tlg +* zc-class-scrbook01.tlg +* zc-class-scrbook01.xetex.tlg +* zc-class-scrreprt01.luatex.tlg +* zc-class-scrreprt01.tlg +* zc-class-scrreprt01.xetex.tlg +* zc-compat-amsmath01.luatex.tlg +* zc-compat-amsmath01.tlg +* zc-compat-amsmath01.xetex.tlg +* zc-compat-appendices01.luatex.tlg +* zc-compat-appendices01.tlg +* zc-compat-appendices01.xetex.tlg +* zc-compat-appendix01.luatex.tlg +* zc-compat-appendix01.tlg +* zc-compat-appendix01.xetex.tlg +* zc-compat-breqn01.luatex.tlg +* zc-compat-breqn01.tlg +* zc-compat-breqn01.xetex.tlg +* zc-compat-enumitem01.luatex.tlg +* zc-compat-enumitem01.tlg +* zc-compat-enumitem01.xetex.tlg +* zc-compat-koma-script01.luatex.tlg +* zc-compat-koma-script01.tlg +* zc-compat-koma-script01.xetex.tlg +* zc-compat-listings01.luatex.tlg +* zc-compat-listings01.tlg +* zc-compat-listings01.xetex.tlg +* zc-compat-memoir01.luatex.tlg +* zc-compat-memoir01.tlg +* zc-compat-memoir01.xetex.tlg +* zc-compat-subcaption01.luatex.tlg +* zc-compat-subcaption01.tlg +* zc-compat-subcaption01.xetex.tlg +* zc-compat-subfig01.luatex.tlg +* zc-compat-subfig01.tlg +* zc-compat-subfig01.xetex.tlg +* zc-dictionaries01.tlg +* zc-dictionaries02.luatex.tlg +* zc-dictionaries02.tlg +* zc-dictionaries02.xetex.tlg +* zc-howto-amsmath01.luatex.tlg +* zc-howto-amsmath01.tlg +* zc-howto-amsmath01.xetex.tlg +* zc-howto-enumitem01.luatex.tlg +* zc-howto-enumitem01.tlg +* zc-howto-enumitem01.xetex.tlg +* zc-howto-listings01.luatex.tlg +* zc-howto-listings01.tlg +* zc-howto-listings01.xetex.tlg +* zc-howto-newfloat01.luatex.tlg +* zc-howto-newfloat01.tlg +* zc-howto-newfloat01.xetex.tlg +* zc-howto-newfloat02.luatex.tlg +* zc-howto-newfloat02.tlg +* zc-howto-newfloat02.xetex.tlg +* zc-howto-newfloat03.luatex.tlg +* zc-howto-newfloat03.tlg +* zc-howto-newfloat03.xetex.tlg +* zc-howto-newfloat04.luatex.tlg +* zc-howto-newfloat04.tlg +* zc-howto-newfloat04.xetex.tlg +* zc-howto-newfloat05.luatex.tlg +* zc-howto-newfloat05.tlg +* zc-howto-newfloat05.xetex.tlg +* zc-howto-newtheorem01.luatex.tlg +* zc-howto-newtheorem01.tlg +* zc-howto-newtheorem01.xetex.tlg +* zc-howto-newtheorem02.luatex.tlg +* zc-howto-newtheorem02.tlg +* zc-howto-newtheorem02.xetex.tlg +* zc-howto-newtheorem03.luatex.tlg +* zc-howto-newtheorem03.tlg +* zc-howto-newtheorem03.xetex.tlg +* zc-howto-newtheorem04.luatex.tlg +* zc-howto-newtheorem04.tlg +* zc-howto-newtheorem04.xetex.tlg +* zc-howto-zref-xr01.luatex.tlg +* zc-howto-zref-xr01.tlg +* zc-howto-zref-xr01.xetex.tlg +* zc-label-options01.luatex.tlg +* zc-label-options01.tlg +* zc-languages01.tlg +* zc-opt-check01.luatex.tlg +* zc-opt-check01.tlg +* zc-opt-d01.tlg +* zc-opt-g01.tlg +* zc-opt-hyperref01.luatex.tlg +* zc-opt-hyperref01.tlg +* zc-opt-hyperref01.xetex.tlg +* zc-opt-hyperref02.luatex.tlg +* zc-opt-hyperref02.tlg +* zc-opt-hyperref02.xetex.tlg +* zc-opt-hyperref03.luatex.tlg +* zc-opt-hyperref03.tlg +* zc-opt-hyperref03.xetex.tlg +* zc-opt-hyperref04.luatex.tlg +* zc-opt-hyperref04.tlg +* zc-opt-hyperref04.xetex.tlg +* zc-opt-hyperref05.luatex.tlg +* zc-opt-hyperref05.tlg +* zc-opt-hyperref05.xetex.tlg +* zc-opt-lang01.luatex.tlg +* zc-opt-lang01.tlg +* zc-opt-lang01.xetex.tlg +* zc-opt-lang02.luatex.tlg +* zc-opt-lang02.tlg +* zc-opt-lang02.xetex.tlg +* zc-opt-lang03.luatex.tlg +* zc-opt-lang03.tlg +* zc-opt-lang03.xetex.tlg +* zc-opt-lang04.luatex.tlg +* zc-opt-lang04.tlg +* zc-opt-lang04.xetex.tlg +* zc-opt-lang05.luatex.tlg +* zc-opt-lang05.tlg +* zc-opt-lang05.xetex.tlg +* zc-opt-lang06.luatex.tlg +* zc-opt-lang06.tlg +* zc-opt-lang06.xetex.tlg +* zc-opt-nocompat01.luatex.tlg +* zc-opt-nocompat01.tlg +* zc-opt-nocompat01.xetex.tlg +* zc-opt-nocompat02.luatex.tlg +* zc-opt-nocompat02.tlg +* zc-opt-nocompat02.xetex.tlg +* zc-opt-nocompat03.luatex.tlg +* zc-opt-nocompat03.tlg +* zc-opt-nocompat03.xetex.tlg +* zc-opt-ref01.tlg +* zc-opt-ref02.luatex.tlg +* zc-opt-ref02.tlg +* zc-opt-ref02.xetex.tlg +* zc-opt-titleref01.luatex.tlg +* zc-opt-titleref01.tlg +* zc-opt-titleref01.xetex.tlg +* zc-precedence-rules01.luatex.tlg +* zc-precedence-rules01.tlg +* zc-precedence-rules01.xetex.tlg +* zc-sort01.tlg +* zc-typeset01.luatex.tlg +* zc-typeset01.tlg +* zc-typeset01.xetex.tlg +* zc-workaround-breqn01.luatex.tlg +* zc-workaround-breqn01.tlg +* zc-workaround-breqn01.xetex.tlg +* zc-zcref-options01.luatex.tlg +* zc-zcref-options01.tlg +* zc-zcref-options01.xetex.tlg + + +## TDS manifest + +The following groups list the files included in the TeX Directory Structure used to install +the package into a TeX distribution. + +### Source files (TDS) + +All files included in the `zref-clever/source` directory. + +* zref-clever.dtx +* zref-clever.ins + +### TeX files (TDS) + +All files included in the `zref-clever/tex` directory. + +* zref-clever-english.dict +* zref-clever-french.dict +* zref-clever-german.dict +* zref-clever-portuguese.dict +* zref-clever-spanish.dict +* zref-clever.sty + +### Doc files (TDS) + +All files included in the `zref-clever/doc` directory. + +* CHANGELOG.md +* DEPENDS.txt +* MANIFEST.md +* README.md +* zref-clever-code.pdf +* zref-clever-code.tex +* zref-clever.pdf +* zref-clever.tex + + +## CTAN manifest + +The following group lists the files included in the CTAN package. + +### CTAN files + +* CHANGELOG.md +* DEPENDS.txt +* MANIFEST.md +* README.md +* zref-clever-code.pdf +* zref-clever-code.tex +* zref-clever.dtx +* zref-clever.ins +* zref-clever.pdf +* zref-clever.tex diff --git a/Master/texmf-dist/doc/latex/zref-clever/README.md b/Master/texmf-dist/doc/latex/zref-clever/README.md new file mode 100644 index 00000000000..b260c87ec06 --- /dev/null +++ b/Master/texmf-dist/doc/latex/zref-clever/README.md @@ -0,0 +1,22 @@ +# zref-clever + +**Clever LaTeX cross-references based on zref** + +Author: Gustavo Barros +Maintainer: Gustavo Barros + +`zref-clever` provides an user interface for making LaTeX cross-references +which automates some of their typical features, thus easing their input in the +document and improving the consistency of typeset results. A reference made +with `\zcref` includes a "name" according to its "type" and lists of multiple +labels can be automatically sorted and compressed into ranges when due. The +reference format is highly and easily customizable, both globally and locally. +`zref-clever` is based on `zref`'s extensible referencing system. + +License: LPPL Version 1.3c + +Repository: https://github.com/gusbrs/zref-clever + +Bug tracker: https://github.com/gusbrs/zref-clever/issues + +CTAN: https://ctan.org/pkg/zref-clever diff --git a/Master/texmf-dist/doc/latex/zref-clever/zref-clever-code.pdf b/Master/texmf-dist/doc/latex/zref-clever/zref-clever-code.pdf new file mode 100644 index 00000000000..b8105bc9e2c Binary files /dev/null and b/Master/texmf-dist/doc/latex/zref-clever/zref-clever-code.pdf differ diff --git a/Master/texmf-dist/doc/latex/zref-clever/zref-clever-code.tex b/Master/texmf-dist/doc/latex/zref-clever/zref-clever-code.tex new file mode 100644 index 00000000000..a258484cccb --- /dev/null +++ b/Master/texmf-dist/doc/latex/zref-clever/zref-clever-code.tex @@ -0,0 +1,53 @@ +% \iffalse meta-comment +% +% File: zref-clever-code.tex +% +% This file is part of the LaTeX package "zref-clever". +% +% Copyright (C) 2021 Gustavo Barros +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file: +% +% https://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 is "maintained" (as per LPPL maintenance status) by +% Gustavo Barros. +% +% This work consists of the files zref-clever.dtx, +% zref-clever.ins, +% zref-clever.tex, +% zref-clever-code.tex, +% and the derived files listed in MANIFEST.md. +% +% The released version of this package is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the package can be found at +% +% https://github.com/gusbrs/zref-clever +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +% \fi + +\documentclass{l3doc} + +% Have \GetFileInfo pick up date and version data and used in the +% documentation. +\usepackage[cap,nameinlink=false,check,titleref]{zref-clever} + +\begin{document} + +\DocInput{zref-clever.dtx} + +\end{document} diff --git a/Master/texmf-dist/doc/latex/zref-clever/zref-clever.pdf b/Master/texmf-dist/doc/latex/zref-clever/zref-clever.pdf new file mode 100644 index 00000000000..1b0c6f93f92 Binary files /dev/null and b/Master/texmf-dist/doc/latex/zref-clever/zref-clever.pdf differ diff --git a/Master/texmf-dist/doc/latex/zref-clever/zref-clever.tex b/Master/texmf-dist/doc/latex/zref-clever/zref-clever.tex new file mode 100644 index 00000000000..c2fa9f19b2c --- /dev/null +++ b/Master/texmf-dist/doc/latex/zref-clever/zref-clever.tex @@ -0,0 +1,2163 @@ +% \iffalse meta-comment +% +% File: zref-clever.tex +% +% This file is part of the LaTeX package "zref-clever". +% +% Copyright (C) 2021 Gustavo Barros +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file: +% +% https://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 is "maintained" (as per LPPL maintenance status) by +% Gustavo Barros. +% +% This work consists of the files zref-clever.dtx, +% zref-clever.ins, +% zref-clever.tex, +% zref-clever-code.tex, +% and the derived files listed in MANIFEST.md. +% +% The released version of this package is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the package can be found at +% +% https://github.com/gusbrs/zref-clever +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +% \fi + +\documentclass{l3doc} + +% The package itself *must* be loaded so that \GetFileInfo can pick up date +% and version data. Naturally, we also use it. +\usepackage[cap,check,titleref]{zref-clever} + +\usepackage[T1]{fontenc} + +\usepackage[sc]{mathpazo} +\linespread{1.05} +\usepackage[scale=.88]{tgheros} % sans +\usepackage[varqu,scaled=1.03]{inconsolata} % tt + +\usepackage{listings} + +\usepackage{microtype} + +\hypersetup{hidelinks} + +\NewDocumentCommand\opt{m}{\texttt{#1}} + +\definecolor{reffmtbox}{gray}{0.15} +\definecolor{reffmtback}{gray}{0.85} +\NewDocumentCommand\reffmt{m}{% + \fcolorbox{reffmtbox}{reffmtback}{% + \rule[-0.2\baselineskip]{0pt}{0.8\baselineskip}\texttt{#1}}} + +\newlist{refformat}{itemize}{1} +\setlist[refformat]{label={}, beginpenalty=500, midpenalty=500} + +\NewDocumentCommand\zctask{m}{% + \begin{description} + \item[Task] #1 + \end{description}} + +\lstdefinestyle{code}{ + language=[LaTeX]TeX, + moretexcs={ + AddToHook, + define@key, + patchcmd, + eq@setnumber, + DeclareFloatingEnvironment, + newlist, + setlist, + zexternaldocument, + next@label, + next@label@pre, + @empty, + tag, + text, + lstset, + condition, + } +} +\lstdefinestyle{zrefclever}{ + style=code, + moretexcs={ + zcref, + zcpageref, + zlabel, + zcsetup, + zcLanguageSetup, + zcRefTypeSetup, + zcheck, + } +} +\lstset{ + style=zrefclever, + basicstyle=\ttfamily\small, + columns=fullflexible, + keepspaces, + xleftmargin=\leftmargin, + xrightmargin=.5\leftmargin, +} +% Setup inspired by https://tex.stackexchange.com/a/4068. For how to use these +% environments in a .dtx context see https://tex.stackexchange.com/a/31026. +\newcounter{zchowto} +\lstnewenvironment{zchowto}[1][]{% + \renewcommand{\lstlistingname}{How-to}% + \lstset{#1}% + \setcounter{lstlisting}{\value{zchowto}}% +}{} +\newcounter{zcworkaround} +\lstnewenvironment{zcworkaround}[1][]{% + \renewcommand{\lstlistingname}{Work-around}% + \lstset{#1}% + \setcounter{lstlisting}{\value{zcworkaround}}% +}{} +\lstnewenvironment{zcexample}[1][]{% + \renewcommand{\lstlistingname}{Example}% + \lstset{#1}% +}{} +\ExplSyntaxOn +\makeatletter +\lst@AddToHook { PreInit } + { + \cs_if_exist:cT { c@ \lstenv@name } + { \exp_args:Nx \refstepcounter { \lstenv@name } } + } +\makeatother +\ExplSyntaxOff + +\zcRefTypeSetup{zchowto}{ + Name-sg = {How-to}, + name-sg = {how-to}, + Name-pl = {How-tos}, + name-pl = {how-tos}, +} +\zcRefTypeSetup{zcworkaround}{ + Name-sg = {Work-around}, + name-sg = {work-around}, + Name-pl = {Work-arounds}, + name-pl = {work-arounds}, +} + +\begin{document} + +\GetFileInfo{zref-clever.sty} + +\title{% + The \pkg{zref-clever} package% + \thanks{This file describes \fileversion, released \filedate.}% +} + +\author{% + Gustavo Barros% + \thanks{\url{https://github.com/gusbrs/zref-clever}}% +} + +\date{\filedate} + +\maketitle + +\begin{abstract} + \pkg{zref-clever} provides an user interface for making \LaTeX{} + cross-references which automates some of their typical features, thus easing + their input in the document and improving the consistency of typeset + results. A reference made with \cs{zcref} includes a ``name'' according to + its ``type'' and lists of multiple labels can be automatically sorted and + compressed into ranges when due. The reference format is highly and easily + customizable, both globally and locally. \pkg{zref-clever} is based on + \pkg{zref}'s extensible referencing system. +\end{abstract} + +\begin{center} + \small + \textbf{EXPERIMENTAL} + + Please read \zcref{sec:warning} carefully. +\end{center} + +\tableofcontents + +\section{Introduction} + +Cross-referencing is an area which lends itself quite naturally to automation. +Not only for input convenience but also, and most importantly, for end results +consistency. Indeed, the standard \LaTeX{} cross-referencing system -- with +\cs{label}, \cs{ref}, and \cs{pageref} -- is already a form of automation, by +relieving us from checking the number of the referenced object, and the page +where it lies. + +But the plethora of existing features, packages and document classes which, in +one way or another, extends this basic functionality is a clear indication of +a demand for more automation. Just to name the most popular: \pkg{cleveref}, +\pkg{hyperref}, \pkg{titleref}, \pkg{nameref}, \pkg{varioref}, \pkg{fancyref}, +and the kernel's \cs{labelformat}. + +However, the standard cross-referencing system stores two, and only two, +properties with the label: the printed representation of the counter last +incremented with \cs{refstepcounter} and the page. Of course, out of the +mentioned desire to automate more, the need arose to store more information +about the label to support this: the title or caption of the referenced +object; its counter or, even better, its ``type'', that is, whether it is a +section, chapter, figure, etc.; its hyperlink anchor, and so on. Thus those +two property ``fields'' of the standard label became quite a disputed real +state. And the packages in this area of functionality were bound to step on +each other's toes as a result. + +Out of this conundrum, Heiko Oberdiek eventually developed \pkg{zref}, which +implements an extensible referencing system, making the labels store a +property list of flexible length, so that new properties can be easily added +and queried. However, even when \pkg{zref} can rightfully boast this powerful +basic concept and is really quite featureful, with several different modules +available, it is fair to say that, for the average user, the package may +appear to be somewhat raw. Indeed, for someone who ``just wants to make a +cross-reference'', the user interface of the \pkg{zref-user} module is akin to +the standard \LaTeX{} cross-referencing system, and even requires some extra +work if you want to have a hyperlinked reference. In other words, \pkg{zref} +seems to have focused on infrastructure and on performing a number of +specialized tasks with different modules, and a large part of the landscape of +automation features available for the standard referencing system was not +carried over to \pkg{zref}, neither by the \pkg{zref} itself nor by other +packages. + +\pkg{zref-clever} tries to cover this gap, by bringing a number of existing +features available for the standard referencing system to \pkg{zref}, and +hopefully making \pkg{zref} more accessible, and interesting, to the average +user. And the package's name makes it clear that the core of the envisaged +feature set is that of \pkg{cleveref}, even though the attempt was less one of +replicating functionality per se than that of having it as a successful point +of reference, from where we could then try to tap into \pkg{zref}'s potential. +Indeed, although there is a significant intersection, the features of +\pkg{zref-clever} are neither a superset nor a subset of those of +\pkg{cleveref}. There are things either of them can do that the other can't. +There are also important differences in user interface design. In particular, +\pkg{zref-clever} relies heavily on \texttt{key=value} interfaces both for +general configuration and for centering in a single user command, \cs{zcref}, +as the main entrance for reference making, whose behavior can be modulated by +local options. + +Considering that \pkg{zref} itself offers the \pkg{zref-titleref} module, and +that the integration with \pkg{zref-check} allows \pkg{zref-clever} to make +context sensitive references, akin to those of \pkg{varioref}, a significant +part of the most prominent automation features available to the standard +referencing system is thus brought to \pkg{zref}, working under a single +consistent underlying infrastructure and user interface. Alas, there are +limitations, of course (see \zcref{sec:limitations}). Still, all in all, +hopefully \pkg{zref-clever} can be the missing piece for \pkg{zref} to fulfill +the promise insinuated by the ``z'' in its name, and be your ``last ref''. + + +\subsection{Warning} +\zlabel{sec:warning} + +This package is in its early days, and should be considered experimental. By +this I don't mean I expect it to be ``edgy'', indeed quite a lot of effort has +been put into it so that this is not the case. However, during the initial +development, I had to make a number of calls for which I felt I had +insufficient information: in relation to features, packages, or classes I +don't use much, or to languages I don't know well, user needs I found hard to +anticipate etc. Hence, the package needs some time, and some use by more +adventurous people, until it can settle down with more conviction. In the +meantime, polishing the user interface and the infrastructure have a clear +priority over backward compatibility. So, if you choose to use this package, +you should be ready to accommodate to eventual upstream changes. + + +\section{Loading the package} +\zlabel{sec:loading-package} + +As usual: + +\begin{zcexample}[escapeinside=`'] +\usepackage`\oarg{options}'{zref-clever} +\end{zcexample} + + +\subsection{Dependencies} + +\pkg{zref-clever} requires \pkg{zref}, and \LaTeX{} kernel 2021-11-15, or +newer. It also needs \pkg{l3keys2e} and \pkg{ifdraft}. Some packages are +leveraged by \pkg{zref-clever} if they are present, but are not loaded by +default or required by it, namely: \pkg{hyperref}, \pkg{zref-check}, and +\pkg{zref}'s \pkg{zref-titleref}, \pkg{zref-hyperref}, and \pkg{zref-xr} +modules. + + +\section{User interface} +\zlabel{sec:user-interface} + +\begin{function}{\zcref} + \begin{syntax} + \cs{zcref}\meta{*}\oarg{options}\marg{labels} + \end{syntax} +\end{function} +Typesets references to \meta{labels}, given as a comma separated list. When +\pkg{hyperref} support is enabled, references will be hyperlinked to their +respective anchors, according to options. The starred version of the command +does the same as the plain one, just does not form links. The \meta{options} +are (mostly) the same as those of the package, and can be given to local +effect. The \meta{labels} argument is protected by \pkg{zref}'s +\cs{zref@wrapper@babel}, so that it enjoys the same support for \pkg{babel}'s +active characters as \pkg{zref} itself does. + +\begin{function}{\zcpageref} + \begin{syntax} + \cs{zcpageref}\meta{*}\oarg{options}\marg{labels} + \end{syntax} +\end{function} +Typesets page references to \meta{labels}, given as a comma separated list. +It is equivalent to calling \cs{zcref} with the \opt{ref=page} option: +\cs{zcref}\texttt{\meta{*}[}\meta{options}\texttt{,ref=page]}\marg{labels}. + + +\begin{function}{\zcsetup} + \begin{syntax} + \cs{zcsetup}\marg{options} + \end{syntax} +\end{function} +Sets \pkg{zref-clever}'s general options (see \zcref{sec:options, + sec:reference-format}). The settings performed by \cs{zcsetup} are local, +within the current group. But, of course, it can also be used to global +effects if ungrouped, e.g.\ in the preamble. + +\begin{function}{\zcRefTypeSetup} + \begin{syntax} + \cs{zcRefTypeSetup}\marg{type}\marg{options} + \end{syntax} +\end{function} +Sets type-specific reference format options (see \zcref{sec:ref-format-opts}). +Just as for \cs{zcsetup}, the settings performed by \cs{zcRefTypeSetup} are +local, within the current group. + +\bigskip{} + +Besides these, user facing commands related to \zcref*[ref=title, + noname]{sec:internationalization} are presented in +\zcref{sec:internationalization}. Note still that all user commands are +defined with \cs{NewDocumentCommand}, which translates into the usual handling +of arguments by it and/or processing by \pkg{l3keys}, particularly with regard +to brace-stripping and space-trimming. + +Furthermore, \pkg{zref-clever} loads \pkg{zref}'s \pkg{zref-user} module by +default. So you also have its user commands available out of the box, notably +\cs{zlabel}, but also \cs{zref} and \cs{zpageref} themselves. + + + +\subsection{Options} +\zlabel{sec:options} + +\pkg{zref-clever} is highly configurable, offering a lot of flexibility in +typeset results of the references, but it also tries to keep these ``handles'' +as convenient and user friendly as possible. To this end, most of what one +can do with \pkg{zref-clever} (pretty much all of it), can be achieved +directly through the standard and familiar ``comma separated list of +\texttt{key=value} options''. + +There are two main groups of options in \pkg{zref-clever}: ``general +options'', which affect the overall behavior of the package, or the reference +as a whole; and ``reference format options'', which control the detail of +reference formatting, including type-specific and language-specific settings. + +This section covers the first group (for the second one, see +\zcref{sec:ref-format-opts}). General options can be set globally either as +package options at load-time (see \zcref{sec:loading-package}) or by means of +\cs{zcsetup} in the preamble (see \zcref{sec:user-interface}). They can also +be set locally with \cs{zcsetup} along the document or through the optional +argument of \cs{zcref} (see \zcref{sec:user-interface}). Most general options +can be used in any of these contexts, but that is not necessarily true for all +cases, some restrictions may apply, as described in each option's +documentation. + +\bigskip{} + +\DescribeOption{ref} % +\DescribeOption{page} % +The \opt{ref} option controls the label property to which \cs{zcref} refers +to. It can receive \pkg{zref} properties, as long as they are declared, but +notably \texttt{default}, \texttt{page}, \texttt{thecounter} and, if +\pkg{zref-titleref} is loaded, \texttt{title}. The package's default is, +well, \texttt{default}, which is our standard reference. \texttt{thecounter} +is a property set by \pkg{zref-clever} and is similar to \pkg{zref}'s +\texttt{default} property, except that it is not affected by the kernel's +\cs{labelformat}.\footnote{Technical note: the \texttt{default} property + stores \cs{@currentlabel}, while the \texttt{thecounter} property stores + \cs{the}\cs{@currentcounter}. The later is exactly what \cs{refstepcounter} + uses to build \cs{@currentlabel}, except for the \cs{labelformat} prefix + and, hence, has the advantage of being unaffected by it. But the former is + \emph{more reliable} since \cs{@currentlabel} is expected to be correct + pretty much anywhere whereas, although \cs{refstepcounter} does set + \cs{@currentcounter}, it is not everywhere that uses \cs{refstepcounter} for + the purpose. In the cases where the references from these two do diverge, + \pkg{zref-clever} will likely misbehave (reference type, sorting and + compression inevitably depend on a correct \opt{currentcounter}), but using + \texttt{default} at least ensures that the reference itself is correct. + That said, if you do set \cs{labelformat} for some reason, + \texttt{thecounter} may be useful.} By default, reference formatting, +sorting, and compression are done according to information inferred from the +\emph{current counter} (see \opt{currentcounter} option below). Special +treatment in these areas is provided for \texttt{page}, but not for any other +properties. The \opt{page} option is a convenience alias for +\texttt{ref=page}. + +\DescribeOption{typeset} % +\DescribeOption{noname} % +\DescribeOption{noref} % +When \cs{zcref} typesets a set of references, each group of references of the +same type can be, and by default are, preceded by the type's ``name'', and +this is indeed an important feature of \pkg{zref-clever}. This is optional +however, and the \opt{typeset} option controls this behavior. It can receive +values \texttt{ref}, in which case it typesets only the reference(s), +\texttt{name}, in which case it typesets only the name(s), or \texttt{both}, +in which case it typesets, well, both of them. Note that, when value +\texttt{name} is used, the name is still typeset according to the set of +references given to \cs{zcref}. For example, for multiple references, the +plural form is used, capitalization options are honored, etc. Also +hyperlinking behaves just \emph{as if} the references were present and, +depending on the corresponding options, the name may be linked to the first +reference of the type group. The \opt{noname} and \opt{noref} options are +convenience aliases for \texttt{typeset=ref} and \texttt{typeset=name}, +respectively. + +\DescribeOption{sort} % +\DescribeOption{nosort} % +The \opt{sort} option controls whether the list of \meta{labels} received as +argument by \cs{zcref} should be sorted or not. It is a boolean option, and +defaults to \texttt{true}. The \opt{nosort} option is a convenience alias for +\texttt{sort=false}. + +\DescribeOption{typesort} % +\DescribeOption{notypesort} % +Sorting references of the same type can be done with well defined logical +criteria. They either have the same counter or their counters share a clear +hierarchical relation (in the resetting behavior), such that a definite +sorting rule can be inferred from the label's data. The same is not true for +sorting of references of different types. Should ``tables'' come before or +after ``figures''? The \pkg{typesort} option allows to specify the sorting +priority of different reference types. It receives as value a comma separated +list of reference types, specifying that their sorting is to be done in the +order of that list. But \opt{typesort} does not need to receive \emph{all} +possible reference types. The special value \texttt{\{\{othertypes\}\}} (yes, +double braced, one for \pkg{l3keys}, so that the second can make the list) can +be placed anywhere along the list, to specify the sort priority of any type +not included explicitly. If \texttt{\{othertypes\}} is not present in the +list, it is presumed to be at the end of it. Any unspecified types (that is, +those falling implicitly or explicitly into the \texttt{\{othertypes\}} +category) get sorted between themselves in the order of their first appearance +in the label list given as argument to \cs{zcref}. I presume the common use +cases will not need to specify \texttt{\{othertypes\}} at all but, for the +sake of example, if you just really dislike equations, you could use +\texttt{typesort=\{\{\{othertypes\}\}, equation\}}. \opt{typesort}'s default +value is \texttt{\{part, chapter, section, paragraph\}}, which places the +sectioning reference types first in the list, in their hierarchical order, and +leaves everything else to the order of appearance of the labels. The +\opt{notypesort} option behaves like \texttt{typesort=\{\{\{othertypes\}\}\}} +would do, that is, it sorts all types in the order of the first appearance in +the labels' list. + +\DescribeOption{comp} % +\DescribeOption{nocomp} % +\cs{zcref} can automatically compress a set of references of the same type +into a range, when they occur in immediate sequence. The \opt{comp} controls +whether this compression should take place or not. It is a boolean option, +and defaults to \texttt{true}. The \opt{nocomp} option is a convenience alias +for \texttt{comp=false}. Of course, for better compression results the +\opt{sort} is recommended, but the two options are technically independent. + +\DescribeOption{range} % +By default (that is, when the \opt{range} option is not given), \cs{zcref} +typesets a complete list of references according to the \meta{labels} it +received as argument, and only compresses some of them into ranges if the +\opt{comp} option is enabled and if references of the same type occur in +immediate sequence. The \opt{range} option makes \cs{zcref} behave +differently. Sorting is implied by this option (the \opt{sort} option is +disregarded) and, for each reference type group in \meta{labels}, \cs{zcref} +builds a range from the first to the last reference in it, even if references +in between do not occur in immediate sequence. \cs{zcref} is smart enough, +though, to recognize when the first and last references of a type do happen to +be contiguous, in which case it typesets a ``pair'', instead of a ``range''. +It is a boolean option, and the package's default is \texttt{range=false}. +The option given without a value is equivalent to \texttt{range=true} (in the +\pkg{l3keys}' jargon, the \emph{option}'s default is \texttt{true}). + +\DescribeOption{cap} % +\DescribeOption{nocap} % +\DescribeOption{capfirst} % +The \opt{cap} option controls whether the reference type names should be +capitalized or not. It is a boolean option, and the package's default is +\texttt{cap=false}. The option given without a value is equivalent to +\texttt{cap=true}. The \opt{nocap} option is a convenience alias for +\texttt{cap=false}. The \opt{capfirst} option ensures that the reference type +name of the \emph{first} type block is capitalized, even when \opt{cap} is set +to \texttt{false}. + +\DescribeOption{abbrev} % +\DescribeOption{noabbrev} % +\DescribeOption{noabbrevfirst} % +The \opt{abbrev} option controls whether to use abbreviated reference type +names when they are available. It is a boolean option, and the package's +default is \texttt{abbrev=false}. The option given without a value is +equivalent to \texttt{abbrev=true}. The \opt{noabbrev} option is a +convenience alias for \texttt{abbrev=false}. The \opt{noabbrevfirst} ensures +that the reference type name of the \emph{first} type block is never +abbreviated, even when \opt{abbrev} is set to \texttt{true}. + +\DescribeOption{S} % +\opt{S} for ``Sentence''. The \opt{S} option is a convenience alias for +\texttt{capfirst=true, noabbrevfirst=true}, and is intended to be used in +references made at the beginning of a sentence. It is highly recommended that +you make a habit of using the \opt{S} option for beginning of sentence +references. Even if you do happen to be currently using \texttt{cap=true, + abbrev=false}, proper semantic markup will ensure you get expected results +even if you change your mind in that regard later on. For that reason, it was +made short and mnemonic, it can't get any easier. + +\DescribeOption{hyperref} % +The \opt{hyperref} option controls the use of \pkg{hyperref} by +\pkg{zref-clever} and takes values \opt{auto}, \opt{true}, \opt{false}. The +default value, \opt{auto}, makes \pkg{zref-clever} use \pkg{hyperref} if it is +loaded, meaning that references made with \cs{zcref} get hyperlinked to the +anchors of their respective \meta{labels}. \opt{true} does the same thing, +but warns if \pkg{hyperref} is not loaded (\pkg{hyperref} is never loaded for +you). In either of these cases, if \pkg{hyperref} is loaded, module +\pkg{zref-hyperref} is also loaded by \pkg{zref-clever}. \opt{false} means +not to use \pkg{hyperref} regardless of its availability. This is a preamble +only option, but \cs{zcref} provides granular control of hyperlinking by means +of its starred version. + +\DescribeOption{nameinlink} % +The \opt{nameinlink} option controls whether the type name should be included +in the reference hyperlink or not (provided there is a link, of course). +Naturally, the name can only be included in the link of the \emph{first} +reference of each type block. \opt{nameinlink} can receive values +\texttt{true}, \texttt{false}, \texttt{single}, and \texttt{tsingle}. When +the value is \texttt{true} the type name is always included in the hyperlink. +When it is \texttt{false} the type name is never included in the link. When +the value is \texttt{single}, the type name is included in the link only if +\cs{zcref} is typesetting a single reference (not necessarily having received +a single label as argument, as they may have been compressed), otherwise, the +name is left out of the link. When the value is \texttt{tsingle}, the type +name is included in the link for each type block with a single reference, +otherwise, it isn't. An example: suppose you make a couple of references to +something like \cs{zcref}\texttt{\{chap:chapter1\}} and +\cs{zcref}\texttt{\{chap:chapter1, sec:section1, fig:figure1, fig:figure2\}}. +The ``figure'' type name will only be included in the hyperlink if +\opt{nameinlink} option is set to \texttt{true}. If it is set to +\texttt{tsingle}, the first reference will include the name in the link for +``chapter'', as expected, but also in the second reference the ``chapter'' and +``section'' names will be included in their respective links, while that of +``figure'' will not. If the option is set to \texttt{single}, only the name +for ``chapter'' in the first reference will be included in the link, while in +the second reference none of them will. The package's default is +\texttt{nameinlink=tsingle}, and the option given without a value is +equivalent to \texttt{nameinlink=true}. + +\DescribeOption{preposinlink} % +The \opt{preposinlink} option controls whether the \opt{refpre} and +\opt{refpos} reference format options (see \zcref{sec:ref-format-opts}) are +included in the reference hyperlink or not. It is a boolean option. The +package's default is \texttt{preposinlink=false}, and the option given without +a value is equivalent to \texttt{preposinlink=true}. + +\DescribeOption{lang} % +The \opt{lang} option controls the language used by \cs{zcref} when looking +for language-specific reference format options (see +\zcref{sec:ref-format-opts}). The default value, \texttt{current}, uses the +current language, as defined by \pkg{babel} or \pkg{polyglossia} (or +\texttt{english} if none of them is loaded). Value \texttt{main} uses the +main document language, as defined by \pkg{babel} or \pkg{polyglossia} (or +\texttt{english} if none of them is loaded). The \opt{lang} option also +accepts that the language be specified directly by its name, as long as it's a +language known by \pkg{zref-clever}. For more details on +\zcref*[ref=title,noname]{sec:internationalization}, see +\zcref{sec:internationalization}. + +\DescribeOption{d} % +The \opt{d} option sets the declension case, and affects the type name used +for typesetting the reference. Whether this option is operative, and which +values it accepts, depends on the declared setup for each language. For +details, see \zcref{sec:internationalization}. + +\DescribeOption{nudge} % +\DescribeOption{nudgeif} % +\DescribeOption{nonudge} % +\DescribeOption{sg} % +\DescribeOption{g} % +This set of options revolving around \opt{nudge} aims to offer some guard +against mischievous automation on the part of \pkg{zref-clever} by providing a +number of ``nudges'' (compilation time messages) for cases in which you may +wish to revise material \emph{surrounding} the reference -- an article, a +preposition -- according to the reference typeset results. Useful mainly for +languages which inflect the preceding article to gender and/or number, but may +be used generally to fine-tune the language and style around the +cross-references made with \cs{zcref}. The \opt{nudge} option is the main +entrance to this feature and takes values \texttt{true}, \texttt{false}, +\texttt{ifdraft}, or \texttt{iffinal}. The first two, respectively, enable or +disable the ``nudging'' unconditionally. With \texttt{ifdraft}, \opt{nudge} +keeps quiet when option \texttt{draft} is given to \cs{documentclass}, while +with \texttt{iffinal}, nudging is only enabled when option \texttt{final} is +(explicitly) passed to \cs{documentclass}. The option given without a value +is equivalent to \texttt{nudge=true} and the package's default is +\texttt{nudge=false}. \opt{nonudge} is a convenience alias for +\texttt{nudge=false}, and can be used to silence individual references. The +\opt{nudgeif} option controls the events which may trigger a nudge. It takes +a comma separated list of elements, and recognizes values \texttt{multitype}, +\texttt{comptosing}, \texttt{gender}, and \texttt{all}. The +\texttt{multitype} nudge warns when the reference is composed by multiple type +blocks (see \zcref{sec:ref-format-opts}). The \texttt{comptosing} nudge let's +you know when multiple labels of the same type have been compressed to a +singular type name form. It can be combined with the \opt{sg} option, which +is the way to tell \cs{zcref} you know it's a singular and so not to nudge if +a compression to singular occurs, but to nudge if the contrary occurs, that +is, when a plural type name form is employed. The \texttt{gender} nudge must +be combined with option \opt{g}, and depends on the language having support +for it. In essence language dictionaries can store the gender of each type +name (this is done for built-in dictionaries, but can also be done with +\cs{zcLanguageSetup} for languages declared to support it). The \opt{g} +option let's you specify the gender you expect for that particular reference +and the nudge is triggered if there is a mismatch between \opt{g} and the +gender for the type name in the dictionary. Both the \texttt{comptosing} and +the \texttt{gender} nudges have a type block as its scope. See +\zcref{sec:internationalization} for more details and intended use cases of +the ``nudging'' feature. + +\DescribeOption{font} % +The \opt{font} option can receive font styling commands to change the +appearance of the whole reference list (see also the \opt{namefont} and +\opt{reffont} reference format options in \zcref{sec:ref-format-opts}). It +does not affect the content of the \opt{note}, however. The option is +intended exclusively for commands that only change font attributes: style, +family, shape, weight, size, color, etc. Anything else, particularly commands +that may generate typeset output, is not supported. Given how package options +are handled by \LaTeX{}, the fact that this option receives commands as value +means this option \emph{can't} be set at load time, as a package option. If +you want to set it globally, use \cs{zcsetup} instead. + +\DescribeOption{titleref} % +The \opt{titleref} option receives no value and, when given, loads +\pkg{zref}'s \pkg{zref-titleref} module. This is a preamble only option. + +\DescribeOption{note} % +The \opt{note} option receives as value some text to be typeset at the end of +the whole reference list. It is separated from it by \opt{notesep} (see +\zcref{sec:ref-format-opts}). + +\DescribeOption{check} % +Provides integration of \pkg{zref-clever} with the \pkg{zref-check} package. +In the preamble, the \opt{check} option receives no value and, when given, +loads \pkg{zref-check}. In the document body, \opt{check} requires a value, +which works exactly like the optional argument of \cs{zcheck}, and can receive +both checks and \cs{zcheck}'s options. And the checks are performed for each +label in \marg{labels} received as argument by \cs{zcref}. See the User +manual of \pkg{zref-check} for details. The checks done by the \opt{check} +option in \cs{zcref} comprise the complete reference, including the \opt{note} +(see \zcref{sec:ref-format-opts}). If \pkg{zref-check} was not loaded in the +preamble, at begin document the option is made no-op and issues a warning. + +\DescribeOption{countertype} % +The \opt{countertype} option allows to specify the ``reference type'' of each +counter, which is stored as a label property when the label is set. This +``reference type'' is what determines how a reference to this label will +eventually be typeset when it is referred to (see +\zcref{sec:reference-types}). A value like \texttt{countertype = \{foo = + bar\}} sets the \texttt{foo} counter to use the reference type \texttt{bar}. +There's only need to specify the \opt{countertype} for counters whose name +differs from that of their type, since \pkg{zref-clever} presumes the type has +the same name as the counter, unless otherwise specified. Also, the default +value of the option already sets appropriate types for basic \LaTeX{} +counters, including those from the standard classes. Setting a counter type +to an empty value removes any (explicit) type association for that counter, in +practice, this means it then uses a type equal to its name. Since this option +only affects how labels are set, it is not available in \cs{zcref}. + +\DescribeOption{\raisebox{-.2em}{\dbend}\ counterresetters} % +\DescribeOption{counterresetby} % +The sorting and compression of references done by \cs{zcref} requires that we +know the counter associated with a particular label but also information on +any counter whose stepping may trigger its resetting, or its ``enclosing +counters''. This information is not easily retrievable from the counter +itself but is (normally) stored with the counter that does the resetting. The +\opt{counterresetters} option adds counter names, received as a comma +separated list, to the list of counters \pkg{zref-clever} uses to search for +``enclosing counters'' of the counter for which a label is being set. +Unfortunately, not every counter gets reset through the standard machinery for +this, including some \LaTeX{} kernel ones (e.g. the \texttt{enumerate} +environment counters). For those, there is really no way to retrieve this +information directly, so we have to just tell \pkg{zref-clever} about them. +And that's what the \opt{counterresetby} option is made for. It receives a +comma separated list of \texttt{key=value} pairs, in which \texttt{key} is the +counter, and \texttt{value} is its ``enclosing counter'', that is, the counter +whose stepping results in its resetting. This is not really an ``option'' in +the sense of ``user choice'', it is more of a way to inform \pkg{zref-clever} +of something it cannot know or automatically find in general. One cannot +place arbitrary information there, or \pkg{zref-clever} can be thoroughly +confused. The setting must correspond to the actual resetting behavior of the +involved counters. \opt{counterresetby} has precedence over the search done +in the \opt{counterresetters} list. The default value of +\opt{counterresetters} includes the counters for sectioning commands of the +standard classes which, in most cases, should be the relevant ones for +cross-referencing purposes. The default value of \opt{counterresetby} +includes the \texttt{enumerate} environment counters. So, hopefully, you +don't need to ever bother with either of these options. But, if you do, they +are here. Use them with caution though. Since these options only affect how +labels are set, they are not available in \cs{zcref}. + +\DescribeOption{\raisebox{.4em}{\dbend}\ currentcounter} % +\LaTeX{}'s \cs{refstepcounter} sets two variables which potentially affect the +\cs{zlabel} set after it: \cs{@currentlabel} and \cs{@currentcounter}. +Actually, traditionally, only the current label was thus stored, the current +counter was added to \cs{refstepcounter} somewhat recently (with the +2020-10-01 kernel release). But, since \pkg{zref-clever} relies heavily on +the information of what the current counter is, it must set \pkg{zref} to +store that information with the label, as it does. As long as the document +element we are trying to refer to uses the standard machinery of +\cs{refstepcounter} we are on solid ground and can retrieve the correct +information. However, it is not always ensured that \cs{@currentcounter} is +kept up to date. For example, packages which handle labels specially, for one +reason or another, may or may not set \cs{@currentcounter} as required. +Considering the addition of \cs{@currentcounter} to \cs{refstepcounter} itself +is not that old, it is likely that in a good number of places a reliable +\cs{@currentcounter} is not really in place. Therefore, it may happen we need +to tell \pkg{zref-clever} what the current counter is in certain +circumstances, and that's what \opt{currentcounter} does. The same as with +the previous two options, this is not really an ``user choice'' kind of +option, but a way to tell \pkg{zref-clever} a piece of information it has no +means to retrieve automatically. The setting must correspond to the actual +``current counter'', meaning here ``the counter underlying +\cs{@currentlabel}'' in a given situation. Also, when using the +\opt{currentcounter} option, make sure the setting is duly grouped because, if +set, it has precedence over \cs{@currentcounter} and, contrary to the later, +the former is not reset the next time \cs{refstepcounter} runs. Its default +value is, quite naturally, \cs{@currentcounter}. Since this option only +affects how labels are set, it is not available in \cs{zcref}. + +\DescribeOption{nocompat} % +Some packages, document classes, or LaTeX features may require specific +support to work with \pkg{zref-clever} (see \zcref{sec:limitations}). +\pkg{zref-clever} tries to make things smoother by covering some of them. +Depending on the case, this can take the form of some simple setup for +\pkg{zref-clever}, or may involve the use of hooks to external environments or +commands and, eventually, a patch or redefinition. By default, all the +available compatibility modules are enabled. Should this be undesired or +cause any problems in your environment, the option \opt{nocompat} can +selectively or completely inhibit their loading. \opt{nocompat} receives a +comma separated list of compatibility modules to disable (for the list of +available modules and details about each of them, see +\zcref{sec:comp-modules}). You can disable all modules by setting +\opt{nocompat} without a value (or an empty one). This is a preamble only +option. + +\section{Reference format} +\zlabel{sec:reference-format} + +\subsection{Reference types} +\zlabel{sec:reference-types} + +A ``reference type'' is the basic \pkg{zref-clever} setup unit for specifying +how a cross-reference group of a certain kind is to be typeset. Though, +usually, it will have the same name as the underlying \LaTeX{} \emph{counter}, +they are conceptually different. \pkg{zref-clever} sets up \emph{reference + types} and an association between each \emph{counter} and its \emph{type}, +it does not define the counters themselves, which are defined by your +document. One \emph{reference type} can be associated with one or more +\emph{counters}, and a \emph{counter} can be associated with different +\emph{types} at different points in your document. But each label is stored +with only one \emph{type}, as specified by the counter-type association at the +moment it is set, and that determines how the reference to that label is +typeset. References to different \emph{counters} of the same \emph{type} are +grouped together, and treated alike by \cs{zcref}. A \emph{reference type} +may be known to \pkg{zref-clever} when the \emph{counter} it is associated +with is not actually defined, and this inconsequential. In practice, the +contrary may also happen, a \emph{counter} may be defined but we have no +\emph{type} for it, but this must be handled by \pkg{zref-clever} as an error +(at least, if we try to refer to it), usually a ``missing name'' error. + +\pkg{zref-clever} provides default settings for the following reference types: +\texttt{part}, \texttt{chapter}, \texttt{section}, \texttt{paragraph}, +\texttt{appendix}, \texttt{subappendix}, \texttt{page}, \texttt{line}, +\texttt{figure}, \texttt{table}, \texttt{item}, \texttt{footnote}, +\texttt{endnote}, \texttt{note}, \texttt{equation}, \texttt{theorem}, +\texttt{lemma}, \texttt{corollary}, \texttt{proposition}, \texttt{definition}, +\texttt{proof}, \texttt{result}, \texttt{remark}, \texttt{example}, +\texttt{algorithm}, \texttt{listing}, \texttt{exercise}, and +\texttt{solution}. Therefore, if you are using a language for which +\pkg{zref-clever} has built-in support (see \zcref{sec:internationalization}), +these reference types are available for use out of the box.\footnote{There may + be slight availability differences depending on the language, but + \pkg{zref-clever} strives to keep this complete list available for the + languages it has built-in dictionaries.} And, in any case, it is always +easy to setup custom reference types with \cs{zcRefTypeSetup} or +\cs{zcLanguageSetup} (see \zcref{sec:user-interface, sec:reference-format, + sec:internationalization}). + +The association of a \emph{counter} to its \emph{type} is controlled by the +\opt{countertype} option. As seen in its documentation, \pkg{zref-clever} +presumes the \emph{type} to be the same as the \emph{counter} unless +instructed otherwise by that option. This association, as determined by the +local value of the option, affects how the \emph{label} is set, which stores +the type among its properties. However, when it comes to typesetting, that is +from the perspective of \cs{zcref}, only the \emph{type} matters. In other +words, how the reference is supposed to be typeset is determined at the point +the \emph{label} gets set. In sum, they may be namesakes (or not), but type +is type and counter is counter. + +Indeed, a reference type can be associated with multiple counters because we +may want to refer to different document elements, with different +\emph{counters}, as a single \emph{type}, with a single name. One prominent +case of this are sectioning commands. \cs{section}, \cs{subsection}, and +\cs{subsubsection} have each their counter, but we'd like to refer to all of +them by ``sections'' and group them together. The same for \cs{paragraph} and +\cs{subparagraph}. + +There are also cases in which we may want to use different \emph{reference + types} to refer to document objects sharing the same \emph{counter}. +Notably, the environments created with \LaTeX{}'s \cs{newtheorem} command and +the \cs{appendix}. + + +One more observation about ``reference types'' is due here. A \emph{type} is +not really ``defined'' in the sense a variable or a function is. It is more +of a ``string'' which \pkg{zref-clever} uses to look for a whole set of +type-specific reference format options (see \zcref{sec:ref-format-opts}). +Each of these options individually may be ``set'' or not, ``defined'' or not. +And, depending on the setup and the relevant precedence rules for this, some +of them may be required and some not. In practice, \pkg{zref-clever} uses the +\emph{type} to look for these options when it needs one, and issues a +compilation warning when it cannot find a suitable value. + + +\subsection{Reference format options} +\zlabel{sec:ref-format-opts} + +Formatting how the reference is to be typeset is, quite naturally, a big part +of the user interface of \pkg{zref-clever}. In this area, we tried to balance +``flexibility'' and ``user friendliness''. But the former does place a big +toll overall, since there are indeed many places where tweaking may be +desired, and the settings may depend on at least two important dimensions of +variation: the reference type and the language. Combination of those +necessarily makes for a large set of possibilities. Hence, the attempt here +is to provide a rich set of ``handles'' for fine tuning the reference format +but, at the same time, do not \emph{require} detailed setup by the users, +unless they really want it. + +With that in mind, we have settled with an user interface for reference +formatting which allows settings to be done in different scopes, with more or +less overarching effects, and some precedence rules to regulate the relation +of settings given in each of these scopes. There are four scopes in which +reference formatting can be specified by the user, in the following precedence +order: i) as \emph{general options}; ii) as \emph{type-specific options}; iii) +as \emph{language-specific and type-specific translations}; and iv) as +\emph{default translations} (that is, language-specific but not +type-specific). Besides those, there's a fifth \emph{internal} scope, with +the least priority of all, a ``fallback'', for the cases where it is +meaningful to provide some value, even for an unknown language. The package +itself places the default setup for reference formatting at low precedence +levels, and the users can easily and conveniently override them as desired. + +``General options'' (i) can be given by the user in the optional argument of +\cs{zcref}, but also set through \cs{zcsetup} or even, depending on the case, +as package options at load-time (see \zcref{sec:options}).\footnote{The use of + \cs{zcsetup} for global reference format settings is recommended though. + Whether you can use load-time options or not depends on the values of the + options: due to how \LaTeX{} handles package options, if the values of the + options you are setting include \emph{commands} you can't set them at + load-time, and rather \emph{must} use \cs{zcsetup}.} ``Type-specific +options'' (ii) are handled by \cs{zcRefTypeSetup} (see +\zcref{sec:user-interface}). ``Language-specific translations'', be they +``type-specific'' (iii) or ``default'' (iv) have their user interface in +\cs{zcLanguageSetup}, and have their values populated by the package's +built-in dictionaries (see \zcref{sec:internationalization}). Not all +reference format specifications can be given in all of these scopes, though. +Some of them can't be type-specific, others must be type-specific, so the set +available in each scope depends on the pertinence of the case. +\zcref{tab:reference-format} introduces the available reference format +options, which will be discussed in more detail soon, and lists the scopes in +which each is available. + + +\begin{table}[htb] + \centering + \begin{tabular}{l>{\ttfamily}lcccc} + \toprule + & & General & Type & Type-specific & Default \\ + & & options & options & translations & translations \\ + & & (i) & (ii) & (iii) & (iv) \\ + + \midrule + Necessarily not & tpairsep & $\bullet$ & & & $\bullet$ \\ + type-specific & tlistsep & $\bullet$ & & & $\bullet$ \\ + & tlastsep & $\bullet$ & & & $\bullet$ \\ + & notesep & $\bullet$ & & & $\bullet$ \\ + + \addlinespace + Possibly & namesep & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ \\ + type-specific & pairsep & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ \\ + & listsep & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ \\ + & lastsep & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ \\ + & rangesep & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ \\ + & refpre & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ \\ + & refpos & $\bullet$ & $\bullet$ & $\bullet$ & $\bullet$ \\ + + \addlinespace + Necessarily & Name-sg & & $\bullet$ & $\bullet$ & \\ + type-specific & name-sg & & $\bullet$ & $\bullet$ & \\ + & Name-pl & & $\bullet$ & $\bullet$ & \\ + & name-pl & & $\bullet$ & $\bullet$ & \\ + & Name-sg-ab & & $\bullet$ & $\bullet$ & \\ + & name-sg-ab & & $\bullet$ & $\bullet$ & \\ + & Name-pl-ab & & $\bullet$ & $\bullet$ & \\ + & name-pl-ab & & $\bullet$ & $\bullet$ & \\ + + \addlinespace + Font & namefont & $\bullet$ & $\bullet$ & & \\ + options & reffont & $\bullet$ & $\bullet$ & & \\ + \bottomrule + \end{tabular} + \caption{Reference format options and their scopes} + \zlabel{tab:reference-format} +\end{table} + + +Understanding the role of each of these reference format options is likely +eased by some visual schemes of how \pkg{zref-clever} builds a reference based +on the labels' data and the value of these options. Take a \texttt{ref} to be +that which a standard \LaTeX{} \cs{ref} would typeset. A \pkg{zref-clever} +``reference block'', or \texttt{ref-block}, is constructed as: + +\begin{refformat} +\item \reffmt{ref-block} \(\equiv\) +\item \reffmt{refpre} \reffmt{ref} \reffmt{refpos} +\end{refformat} + +A \texttt{ref-block} is built for \emph{each} label given as argument to +\cs{zcref}. When the \meta{labels} argument is comprised of multiple labels, +each ``reference type group'', or \texttt{type-group} is potentially made from +the combination of single reference blocks, ``reference block pairs'', +``reference block lists'', or ``reference block ranges'', where each is +respectively built as: + +\begin{refformat} +\item \reffmt{type-group} is a combination of: +\item \reffmt{ref-block} +\item \reffmt{ref-block1} \reffmt{pairsep} \reffmt{ref-block2} +\item \reffmt{ref-block1} \reffmt{listsep} \reffmt{ref-block2} + \reffmt{listsep} \reffmt{ref-block3} \dots{} \par \qquad + \dots{}\reffmt{ref-blockN-1} \reffmt{lastsep} \reffmt{ref-blockN} +\item \reffmt{ref-block1} \reffmt{rangesep} \reffmt{ref-blockN} +\end{refformat} + +To complete a ``type-block'', a \texttt{type-group} only needs to be +accompanied by the ``type name'': + +\begin{refformat} +\item \reffmt{type-block} \(\equiv\) +\item \reffmt{type-name} \reffmt{namesep} \reffmt{type-group} +\end{refformat} + +The \texttt{type-name} is determined not by one single reference format option +but by the appropriate one among the \opt{[Nn]ame-} options according to the +composition of \texttt{type-group} and the general options. The reference +format name options are eight in total: \opt{Name-sg}, \opt{name-sg}, +\opt{Name-pl}, \opt{name-pl}, \opt{Name-sg-ab}, \opt{name-sg-ab}, +\opt{Name-pl-ab}, and \opt{name-pl-ab}. The initial uppercase ``\texttt{N}'' +signals the capitalized form of the type name. The \texttt{-sg} suffix stands +for singular, while \texttt{-pl} for plural. The \texttt{-ab} is appended to +the abbreviated type name form options. When setting up a type, not +necessarily all forms need to be provided. \pkg{zref-clever} will always use +the non-abbreviated form as a fallback to the abbreviated one, if the later is +not available. Hence, if a reference type is not intended to be used with +abbreviated names (the most common case), only the basic four forms are +needed. Besides that, if you are using the \opt{cap} option, only the +capitalized forms will ever be required by \cs{zcref}, so you can get away +setting only \opt{Name-sg} and \opt{Name-pl}. You should not do the contrary +though, and provide only the non-capitalized forms because, even if you are +using the \opt{nocap} option, the capitalized forms will be still required for +\opt{capfirst} and \opt{S} options to work. Whatever the case may be, you +need not worry too much about being remiss in this area: if \cs{zcref} does +lack a name form in any given reference, it will let you know with a +compilation warning (and will typeset the usual missing reference sign: +``\textbf{??}''). + +A complete reference typeset by \cs{zcref} may be comprised of multiple +\texttt{type-block}s, in which case the ``type-block-group'' can also be made +of single type blocks, ``type block pairs'' or ``type block lists'', where +each is respectively built as: + +\begin{refformat} +\item \reffmt{type-block-group} is one of: +\item \reffmt{type-block} +\item \reffmt{type-block1} \reffmt{tpairsep} \reffmt{type-block2} +\item \reffmt{type-block1} \reffmt{tlistsep} \reffmt{type-block2} + \reffmt{tlistsep} \reffmt{type-block3} \dots{} \par \qquad \dots{} + \reffmt{type-blockN-1} \reffmt{tlastsep} \reffmt{type-blockN} +\end{refformat} + +Finally, since \cs{zcref} can also receive an optional \opt{note}, its full +typeset output is built as: + +\begin{refformat} +\item A complete \reffmt{\cs{zcref}} reference: +\item \reffmt{type-block-group} \reffmt{notesep} \reffmt{note} +\end{refformat} + +Reference format options can yet be divided in two general categories: i) +``string'' options, the ones which we have seen thus far, as ``building +blocks'' of the reference; and ii) ``font'' options, which control font +attributes of parts of the reference, namely \opt{namefont} and \opt{reffont}. +These options set the font, respectively, for the \texttt{type-name} and for +\texttt{ref} (to set the font for the whole reference, see the \opt{font} +option in \zcref{sec:options}). ``String'' options is not really a strict +denomination for the first category, but this set of options is intended +exclusively for typesetting material: things you expect to see in the output +of your references. The ``font'' options, on the other hand, are intended +exclusively for commands that only change font attributes: style, family, +shape, weight, size, color, etc. In either case, anything other than their +intended uses is not supported. + +Finally, a comment about the internal ``fallback'' reference format values +mentioned above. These ``last resort'' option values are required by +\pkg{zref-clever} for a clear particular case: if the user loads either +\pkg{babel} or \pkg{polyglossia}, or explicitly sets a language, with a +language that \pkg{zref-clever} does not know and has no dictionary for, it +cannot guess what language that is, and thus has to provide some reasonable +``language agnostic'' default, at least for the options for which this makes +sense (all the ``string'' options, except for the \texttt{[Nn]ame-} ones). +Users do not need to have access to this scope, since they know the language +of their document, or know the values they want for those options, and can set +them as general options, type-specific options, or language options through +the user interface provided for the purpose. But the ``fallback'' options are +documented here so that you can recognize when you are getting these values +and change them appropriately as desired. Though hopefully reasonable, they +may not be what you want. The ``fallback'' option values are the following: + +\begin{zcexample}[escapeinside=`'] +tpairsep = {,`\textvisiblespace{}'} , +tlistsep = {,`\textvisiblespace{}'} , +tlastsep = {,`\textvisiblespace{}'} , +notesep = {`\textvisiblespace{}'} , +namesep = {\nobreakspace} , +pairsep = {,`\textvisiblespace{}'} , +listsep = {,`\textvisiblespace{}'} , +lastsep = {,`\textvisiblespace{}'} , +rangesep = {\textendash} , +refpre = {} , +refpos = {} , +\end{zcexample} + + +\section{Internationalization} +\zlabel{sec:internationalization} + +\pkg{zref-clever} provides internationalization facilities and integrates with +\pkg{babel} and \pkg{polyglossia} to adapt to the languages in use by either +of these language packages, or to a language specified directly by the user. +This is primarily relevant for reference format options, particularly +reference type \emph{names} (though not only, since most reference format +options can have language-specific values, or ``translations'', see +\zcref{sec:ref-format-opts}). But other features of the package also cater +for language specific needs. + +As far as language selection is concerned, if the language is declared and +\pkg{zref-clever} has a built-in ``dictionary'' for it, most use cases will +likely be covered by the \opt{lang} option (see \zcref{sec:options}), and its +values \texttt{current} and \texttt{main}. When the \opt{lang} option is set +to \texttt{current} or \texttt{main}, \pkg{zref-check} will use, respectively, +the \emph{current} or \emph{main} language of the document, as defined by +\pkg{babel} or \pkg{polyglossia}.\footnote{Technically, \pkg{zref-clever} uses + \cs{languagename} and \cs{bbl@main@language} for \pkg{babel}, and + \cs{babelname} and \cs{mainbabelname} for \pkg{polyglossia}, which boils + down to \pkg{zref-clever} always using \emph{\pkg{babel} names} internally, + regardless of which language package is in use. Indeed, an acquainted user + will note that \zcref{tab:languages-and-aliases} contains only \pkg{babel} + language names.} Users can also set \opt{lang} to a specific language +directly, in which case \pkg{babel} and \pkg{polyglossia} are disregarded. +\pkg{zref-clever} provides a number of built-in ``dictionaries'', for the +languages listed in \zcref{tab:languages-and-aliases}, which also includes the +declared aliases to those languages. + +\pkg{zref-clever}'s ``dictionaries'' are loaded sparingly and lazily. A +dictionary for a single language -- that specified by user options in the +preamble, which by default is the current document language -- is loaded at +\texttt{begindocument}. If any other dictionary is needed, it is loaded on +the fly, if and when required. Of course, in either case, conditioned on +availability. In sum, \pkg{zref-clever} loads as little as possible, but +allows for convenient on the fly loading of dictionaries if the values are +indeed required, without users having to worry about it at all. + +\begin{table} + \centering + \begin{tabular}{ll} + \toprule + Language & Aliases \\ + \midrule + english & american \\ + & australian \\ + & british \\ + & canadian \\ + & newzealand \\ + & UKenglish \\ + & USenglish \\ + french & acadian \\ + & canadien \\ + & francais \\ + & frenchb \\ + \bottomrule + \end{tabular} + \quad + \begin{tabular}{ll} + \toprule + Language & Aliases \\ + \midrule + german & austrian \\ + & germanb \\ + & ngerman \\ + & naustrian \\ + & nswissgerman \\ + & swissgerman \\ + portuguese & brazilian \\ + & brazil \\ + & portuges \\ + spanish & \\ + & \\ + \bottomrule + \end{tabular} + \caption{Declared languages and aliases} + \zlabel{tab:languages-and-aliases} +\end{table} + + +But if the built-in dictionaries do not cover your language, or if you'd like +to adjust some of the default language-specific options, this can be done with +\cs{zcDeclareLanguage}, \cs{zcDeclareLanguageAlias}, and +\cs{zcLanguageSetup}.\footnote{Needless to say, if you'd like to contribute a + dictionary or improve an existing one, that is much welcome at + \url{https://github.com/gusbrs/zref-clever/issues}.} + +\begin{function}{\zcDeclareLanguage} + \begin{syntax} + \cs{zcDeclareLanguage}\oarg{options}\marg{language} + \end{syntax} +\end{function} +Declare a new language for use with \pkg{zref-clever}. If \meta{language} has +already been declared, just warn. The \meta{options} argument receives the +usual \texttt{key=value} list and recognizes three keys: \opt{declension}, +\opt{gender}, and \opt{allcaps}. \opt{declension} receives a coma separated +list of valid declension cases for \meta{language}. The first element of the +list is considered to be the default case, both for the \opt{d} option in +\cs{zcref} and for the \opt{case} option in \cs{zcLanguageSetup}. Similarly, +\opt{gender} receives a comma separated list of genders for \meta{language}. +The elements in this list are those which are recognized as valid for the +language for both the \opt{g} option in \cs{zcref} and the \opt{gender} option +in \cs{zcLanguageSetup}. There is no default presumed in this case. Finally, +\opt{allcaps} can be used with languages for which nouns must be always +capitalized for grammatical reasons. For a language declared with the +\opt{allcaps} option, the \opt{cap} reference option (see \zcref{sec:options}) +is disregarded, and \cs{zcref} always uses the capitalized type name forms. +This means that dictionaries for languages with such a trait can be halved in +size, and that user customization for them is simplified, only requiring the +capitalized name forms. On the other hand, the non-capitalized \texttt{name-} +reference format options are rendered no-op for the language in question. +\zcref[S]{tab:language-options} presents an overview of the options in effect +for the languages declared by \pkg{zref-clever}. \cs{zcDeclareLanguage} is +preamble only. + +\begin{table} + \centering + \begin{tabular}{l>{\ttfamily}c>{\ttfamily}c>{\ttfamily}c} + \toprule + Language & declension & gender & allcaps \\ + \midrule + english & -- & -- & -- \\ + french & -- & f,m & -- \\ + german & N,A,D,G & f,m,n & yes \\ + portuguese & -- & f,m & -- \\ + spanish & -- & f,m & -- \\ + \bottomrule + \end{tabular} + \caption{Options for declared languages} + \zlabel{tab:language-options} +\end{table} + +\begin{function}{\zcDeclareLanguageAlias} + \begin{syntax} + \cs{zcDeclareLanguageAlias}\marg{language alias}\marg{aliased language} + \end{syntax} +\end{function} +Declare \meta{language alias} to be an alias of \meta{aliased language}. +\meta{aliased language} must be already known to \pkg{zref-clever}. Once set, +the \meta{language alias} is treated by \pkg{zref-clever} as completely +equivalent to the \meta{aliased language} for any language specification by +the user. \cs{zcDeclareLanguageAlias} is preamble only. + +\begin{function}{\zcLanguageSetup} + \begin{syntax} + \cs{zcLanguageSetup}\marg{language}\marg{options} + \end{syntax} +\end{function} +Sets language-specific reference format options for \meta{language} (see +\zcref{sec:ref-format-opts}), be they type-specific or not. \meta{language} +must be already known to \pkg{zref-clever}. Besides reference format options, +\cs{zcLanguageSetup} knows three other keys: \opt{type}, \opt{case}, and +\opt{gender}. The first two work like a ``switch'' affecting the options +\emph{following} it. For example, if \texttt{type=foo} is given in +\meta{options} the options following it will be set as type-specific options +for reference type \texttt{foo}. Similarly, after \texttt{case=X} (provided +\texttt{X} is a valid declension case for \meta{language}), the following +\texttt{[Nn]ame-} options will set values for the \texttt{X} declension case +(other reference format options are not affected by \opt{case}). Before the +first occurrence of either \opt{type} or \opt{case} default values are set. +For \opt{case} this means the default declension case, which is the first +element of the list provided to the \opt{declension} option in +\cs{zcDeclareLanguage}. For \opt{type} this means ``default translations'', +which are language-specific but not type-specific option values (see +\zcref{sec:ref-format-opts}). An empty valued \texttt{type=} key can also +``unset'' the type. The \opt{gender} key sets the gender of the current +\texttt{type} (provided the value it receives is one of the declared genders +for \meta{language}). \cs{zcLanguageSetup} is preamble only. + +A couple of examples to illustrate the syntax of \cs{zcLanguageSetup}: + +\begin{zcexample} +\zcLanguageSetup{french}{ + type = section , + gender = f , + Name-sg = Section , + name-sg = section , + Name-pl = Sections , + name-pl = sections , +} +\zcLanguageSetup{german}{ + type = section , + gender = m , + case = N , + Name-sg = Abschnitt , + Name-pl = Abschnitte , + case = A , + Name-sg = Abschnitt , + Name-pl = Abschnitte , + case = D , + Name-sg = Abschnitt , + Name-pl = Abschnitten , + case = G , + Name-sg = Abschnitts , + Name-pl = Abschnitte , +} +\end{zcexample} + +\bigskip{} + +As already noted, \pkg{zref-clever} has some support for languages with +declension. This means mainly the declension of \emph{nouns}, which is used +for the reference type names. But some tools are also provided to support the +user in getting better results for the text surrounding a reference, +particularly for numbered and gendered articles, even if those don't have +their typeset output automated. + +For reference type names, the declension cases for each language must be +declared with \cs{zcDeclareLanguage}, and the name reference format options +must be provided for each case, which is done for built-in dictionaries of +languages which have noun declension, and can be done by the user with +\cs{zcLanguageSetup}, as we've seen. \pkg{zref-clever} does not try to guess +or infer the case though, you must tell it to \cs{zcref}. And this is done by +means of the \opt{d} option (see \zcref{sec:options}). So you may write +something like ``\texttt{nach den + \cs{zcref}[d=D]\{sec:section-1,sec:section-2\}}'' to get ``nach den +Abschnitten 1 und 2''. Or ``\texttt{trotz des + \cs{zcref}[d=G]\{eq:theorem-1\}}'' to get ``trotz des Theorems 1''. + +Regarding the text surrounding the reference -- the inflected article, the +passing preposition, etc.\ --, the issue is more delicate. \pkg{zref-clever} +cannot and intends not to typeset those for you. But, depending on the +language, it is true that the kind of automation provided by \pkg{zref-clever} +may betray your best efforts to get a proper surrounding text. Multiple +labels passed to \cs{zcref} may result in singular type names, either because +the labels are of different types, or because they got compressed into a +single reference. References comprised of multiple type blocks may have each +a name with a different gender. Or, worse, \opt{tpairsep}, \opt{tpairsep}, +and \opt{tlastsep} may not provide a general enough way to separate different +type blocks in your language altogether. You may change something in your +document that causes a label to change its type, and hence the gender of the +type name. A page reference to a couple of floats which were by chance on the +same page and all of a sudden no longer are. And so on. + +In this area, the approach taken by \pkg{zref-clever} is to identify some +typical situations in which your attention may be required in reviewing the +surrounding text, and signal it at compilation time. Just like bad boxes, for +example. This feature can be enabled by the \opt{nudge} option (which is +opt-in, see \zcref{sec:options}). There are three ``nudges'' available for +this purpose which trigger messages at different events: \opt{multitype}, +\opt{comptosing}, and \opt{gender}. \opt{multitype} nudges when a reference +is comprised of multiple type blocks. \opt{comptosing} when multiple labels +of the same type block have been compressed into a single one and, hence, the +type name used is singular. Finally, \opt{gender} nudges when there is a +mismatch between the gender specified in \cs{zcref} with the \opt{g} option +and the gender of the type name, as stored in the dictionary or language +settings, for each type block. Which nudges to use is configurable with the +option \opt{nudgeif}. And, if you're sure of the results for a particular +\cs{zcref} call, you can always silence the nudges locally with the +\opt{nonudge} option. + +The main reason to watch for multiple type references with the \opt{multitype} +nudge is that bundling together automatically a list of type blocks is less +smooth an operation than it is for a single reference type. While it arguably +works reasonably well for English, even there it is not always flawless, and +depending on the language, results may range from ``poor style'' to outright +wrong. A typical case would be of that of a language with inflected articles +and a reference with multiple types of different genders or numbers. For +example, in French, with a standard ``\texttt{au \cs{zcref}\{cha:chapter-3, + sec:section-3.1\}}'' we get ``au chapitre 3 et section 3.1'' which sounds +ugly, at best. So we may be better off writing instead ``\texttt{au + \cs{zcref}\{cha:chapter-3\} et à la \cs{zcref}\{sec:section-3.1\}}''. Or +something else, of course. But the general point is that, depending on +circumstances and on the language, the results of automating the grouping of +multiple reference types, as \pkg{zref-clever} is able to do, may leave things +to be desired for. Hence it lets you know when one such case occurs, so that +you can review it for best results. + +The case of the \opt{comptosing} and \opt{gender} nudges is more objective in +nature, they respectively signal mismatches of number and gender. When a +reference is made with \cs{zcref} to a single label we are sure the type name +will be a singular form. However, when \cs{zcref} receives multiple labels of +the same type, the type name will normally be a plural, but not necessarily +so, since the labels may be compressed into a single one (see the \opt{comp} +option in \zcref{sec:options}), in which case the singular is used. The +compression of multiple labels into a single reference should be an exception +for default references, but not so for \opt{page} references, where it is easy +to conceive practical situations where it may occur. Suppose, for example, +you have two contiguous floats in your document and make a page reference to +both of them. Will they end up in the same page or not? Maybe we know what +the current state is, but we cannot know what may happen as the document keeps +being edited. As a consequence, we don't know whether that reference will end +up having a plural or a singular type name. That given, the logic of the +\opt{comptosing} nudge is the following. If we are giving multiple labels to +\cs{zcref}, we can \emph{presume} a plural type name, but we get a nudge in +case the compression of the labels results in a singular type name form. If +one such compression did happen to one of your references, you can use a +singular article and then tell \cs{zcref} you did so with option \opt{sg}. +The effect of the \opt{sg} option is to inhibit the nudge when a compression +to singular occurs, but to do it instead when the compression \emph{ceases} to +occur, that is, if we get a plural type name again at some point. + +The \opt{gender} nudge aims to guard against one particular situation: +possible changes of a reference's type. This does not occur by reason of any +internal behavior of \pkg{zref-clever}, but it may be caused by changes in the +document. You may wish to change one \texttt{theorem} into a +\texttt{proposition} and, if you're writing in French or Portuguese, for +example, that implies that the reference to it changes gender and the likely +preceding article will no longer pass to the reference. The \opt{gender} +nudge requires that the gender of each type name and of each reference be +explicitly specified. For the type names, this is done for the built-in +dictionaries of languages were this matters, and can be done with +\cs{zcLanguageSetup} as well. For the references, that is the purpose of the +\opt{g} option. When there is a mismatch between the two for any type block, +the nudge is triggered. Of couse, this means that the gender markup has to be +supplied in the document at each reference. And considering such type changes +may not be frequent for you, or considered not particularly problematic, +you'll have to balance if doing so is worth it. Still, the feature is +available, and it's up to you. + + +\section{How-tos} + +This section gathers some usage examples, or ``how-tos'', of cases which may +require some \pkg{zref-clever} setup, or usage adjustments, and each item is +set around a cross-reference ``task'' we'd like to perform with +\pkg{zref-clever}. + + +\subsection{Context sensitive references} + +\zctask{Make cross-references which are sensitive to the relative position + between the reference and the label being referred to, à la \pkg{varioref}.} + +\pkg{varioref}'s \cs{vref} provides for varied references for three different +basic cases: when the reference and the label are on the same page, it +typesets a plain reference; when the reference and the label are in contiguous +pages (next, previous, or facing), it typesets the reference and a fixed +string corresponding to the relative position; when the reference and the +label are in different non-contiguous pages, it typesets a regular reference +and a page reference. The same end result, but with a different user +interface concept can be achieved through \pkg{zref-clever}'s integration with +\pkg{zref-check}. For this, the later must be loaded, which can be most +conveniently done with the \opt{check} option in the preamble. With that in +place, the different cases could be covered by the following examples: + +\begin{zcexample} +\zcref[check=thispage]{fig:1} +\zcref[check=nextpage,note={on the following page}]{fig:1} +\zcref[check=prevpage,note={on the preceding page}]{fig:1} +\zcref[check=facing,note={on the facing page}]{fig:1} +\zcref[check=pagegap]{fig:1} on \zcpageref{fig:1} +\end{zcexample} + +And, similarly for the cases of \cs{vpageref}: + +\begin{zcexample} +\zcref[noref,check=thispage,note={on this page}]{fig:1} +\zcref[noref,check=nextpage,note={on the following page}]{fig:1} +\zcref[noref,check=prevpage,note={on the preceding page}]{fig:1} +\zcref[noref,check=facing,note={on the facing page}]{fig:1} +\zcref[noref,check=pagegap]{fig:1} on \zcpageref{fig:1} +\end{zcexample} + +Since \cs{zcref} can receive multiple labels, and make ranges out of them, it +is not difficult to extend these examples to the functionality of +\cs{vrefrange} and \cs{vpagerefrange}. + +Evidently, this does not fully automate the typeset results, but it does +automate the checking that the reference context is the intended one. If the +relation between the reference and the label does not correspond to the +specified one, a compilation warning is issued (according to the options given +to \pkg{zref-check}), so that the problem can be easily identified and +corrected. See \pkg{zref-check}'s documentation for details, and further +available checks. + + +\subsection{\cs{newtheorem}} + +Since \LaTeX{}'s \cs{newtheorem} allows users to create arbitrary numbered +environments, with respective arbitrary counters, the most \pkg{zref-clever} +can do in this regard is to provide some ``typical'' built-in reference types +to smooth user setup but, in the general case, some user setup may be indeed +required. The examples below are equaly valid for \pkg{amsthm}'s +\cs{newtheorem} since, even it provides features beyond those available in the +kernel, its syntax and underlying relation with counters is pretty much the +same. The same for \pkg{ntheorem}. For \pkg{thmtools}' \cs{declaretheorem}, +though some adjustments to the examples below may be required, the basic logic +is the same (there is no integration with the \opt{Refname}, \opt{refname}, +and \opt{label} options, which are targeted to the standard reference system, +but you don't actually need them to get things working conveniently). + + +\subsubsection*{Simple case} + +\zctask{Setup up a new theorem environment created with \cs{newtheorem} to be + referred to with \cs{zcref}. The theorem environment does not share its + counter with other theorem environments, and one of \pkg{zref-clever} + built-in reference types is adequate for my needs.} + +Suppose you set a ``Lemma'' environment with: + +\begin{zcexample} +\newtheorem{lemma}{Lemma}[section] +\end{zcexample} + +In this case, since \pkg{zref-clever} provides a built-in \texttt{lemma} type +(for supported languages) and presumes the reference type to be the same name +as the counter, there is no need for setup, and things just work out of the +box. So, you can go ahead with: + +\begin{zchowto}[caption={\cs{newtheorem}, simple case}] +\documentclass{article} +\usepackage{zref-clever} +\newtheorem{lemma}{Lemma}[section] +\begin{document} +\section{Section 1} +\begin{lemma}\zlabel{lemma-1} + A lemma. +\end{lemma} +\zcref{lemma-1} +\end{document} +\end{zchowto} + +If, however, you had chosen an environment name which did not happen to +coincide with the built-in reference type, all you'd need to do is instruct +\pkg{zref-clever} to associate the counter for your environment to the desired +type with the \opt{countertype} option: + +\begin{zchowto}[caption={\cs{newtheorem}, simple case}] +\documentclass{article} +\usepackage{zref-clever} +\zcsetup{countertype={lem=lemma}} +\newtheorem{lem}{Lemma}[section] +\begin{document} +\section{Section 1} +\begin{lem}\zlabel{lemma-1} + A lemma. +\end{lem} +\zcref{lemma-1} +\end{document} +\end{zchowto} + + +\subsubsection*{Shared counter} + +\zctask{Setup up two new theorem environments created with \cs{newtheorem} to + be referred to with \cs{zcref}. The theorem environments share the same + counter, and the available \pkg{zref-clever} built-in reference types are + adequate for my needs.} + +In this case, we need to set the \opt{countertype} option in the appropriate +contexts, so that the labels of each environment get set with the expected +reference type. As we've seen (at \zcref{sec:user-interface}), \cs{zcsetup} +has local effects, so it can be issued inside the respective environments for +the purpose. Even better, we can leverage the kernel's new hook management +system and just set it for all occurrences with +\cs{AddToHook}\texttt{\{env/\meta{myenv}/begin\}}. + +\begin{zchowto}[caption={\cs{newtheorem}, shared counter}] +\documentclass{article} +\usepackage{zref-clever} +\AddToHook{env/mytheorem/begin}{% + \zcsetup{countertype={mytheorem=theorem}}} +\AddToHook{env/myproposition/begin}{% + \zcsetup{countertype={mytheorem=proposition}}} +\newtheorem{mytheorem}{Theorem}[section] +\newtheorem{myproposition}[mytheorem]{Proposition} +\begin{document} +\section{Section 1} +\begin{mytheorem}\zlabel{theorem-1} + A theorem. +\end{mytheorem} +\begin{myproposition}\zlabel{proposition-1} + A proposition. +\end{myproposition} +\zcref{theorem-1, proposition-1} +\end{document} +\end{zchowto} + + +\subsubsection*{Custom type} + +\zctask{Setup up a new theorem environment created with \cs{newtheorem} to be + referred to with \cs{zcref}. The theorem environment does not share its + counter with other theorem environments, but none of \pkg{zref-clever} + built-in reference types is adequate for my needs.} + +In this case, we need to provide \pkg{zref-clever} with settings pertaining to +the custom reference type we'd like to use. Unless you need to typeset your +cross-references in multiple languages, in which case you'd require +\cs{zcLanguageSetup}, the most convenient way to setup a reference type is +\cs{zcRefTypeSetup}. In most cases, what we really need to provide for a +custom type are the ``type names'' and other reference format options can rely +on default translations already provided by the package (assuming the language +is supported). + +\begin{zchowto}[caption={\cs{newtheorem}, custom type}] +\documentclass{article} +\usepackage{zref-clever} +\newtheorem{myconjecture}{Conjecture}[section] +\zcRefTypeSetup{myconjecture}{ + Name-sg = Conjecture , + name-sg = conjecture , + Name-pl = Conjectures , + name-pl = conjectures , +} +\begin{document} +\section{Section 1} +\begin{myconjecture}\zlabel{conjecture-1} + A conjecture. +\end{myconjecture} +\zcref{conjecture-1} +\end{document} +\end{zchowto} + + +\subsection{\pkg{newfloat}} + +\zctask{Setup a new float environment created with \pkg{newfloat} to be + referred to with \cs{zcref}. None of \pkg{zref-clever} built-in reference + types is adequate for my needs.} + +The case here is pretty much the same as that for \cs{newtheorem} with a +custom type. Hence, we need to setup a corresponding type, for which +providing the ``type names'' should normally suffice. Note that, as far as +\pkg{zref-clever} is concerned, there's nothing specific to the \pkg{newfloat} +package in the setup, the same procedure can be used with \cls{memoir}'s +\cs{newfloat} command or with the \pkg{float}, \pkg{floatrow}, and +\pkg{trivfloat} packages. + +\begin{zchowto}[caption={\pkg{newfloat}}] +\documentclass{article} +\usepackage{newfloat} +\DeclareFloatingEnvironment{diagram} +\usepackage{zref-clever} +\zcRefTypeSetup{diagram}{ + Name-sg = Diagram , + name-sg = diagram , + Name-pl = Diagrams , + name-pl = diagrams , +} +\begin{document} +\section{Section 1} +\begin{diagram} + A diagram. + \caption{A diagram} + \zlabel{diagram-1} +\end{diagram} +\zcref{diagram-1} +\end{document} +\end{zchowto} + + +\subsection{\pkg{amsmath}} + +\zctask{Make references to \pkg{amsmath} display math environments with + \cs{zcref}.} + +Given how \pkg{amsmath}'s display math environments work, they need to handle +\cs{label} specially, and this support is quite hard-wired into the +environments, but it is not extended to \cs{zlabel}. \pkg{zref-clever}'s +\opt{amsmath} compatibility module provides that a \cs{label} used inside +these environments set both a regular \cs{label} and a \cs{zlabel}, so that we +can refer to the equations with both referencing systems. Note the use of +\cs{zlabel} for \env{subequations} though. For more details, see the +description of the \opt{amsmath} compatibility module at +\zcref{sec:comp-modules}. + +\begin{zchowto}[caption={\pkg{amsmath}},label={how:amsmath}] +\documentclass{article} +\usepackage{amsmath} +\usepackage{zref-clever} +\usepackage{hyperref} +\begin{document} +\section{Section 1} +\begin{equation}\label{eq:1} + A^{(1)}_l =\begin{cases} n!,&\text{if }l =1\\ + 0,&\text{otherwise}.\end{cases} +\end{equation} +\begin{equation*} \tag{foo}\label{eq:2} + A^{(1)}_l =\begin{cases} n!,&\text{if }l =1\\ + 0,&\text{otherwise}.\end{cases} +\end{equation*} +\begin{subequations}\zlabel{eq:3} + \begin{align} + A+B&=B+A\\ + C&=D+E\label{eq:3b}\\ + E&=F + \end{align} +\end{subequations} +\zcref{eq:1, eq:2, eq:3, eq:3b} +\end{document} +\end{zchowto} + + +\subsection{\pkg{listings}} + +\zctask{Make references to a \env{lstlisting} environment from the + \pkg{listings} package with \cs{zcref}.} + +Being \env{lstlisting} a verbatim environment, setting labels inside it +requires special treatment. \pkg{zref-clever}'s \opt{listings} compatibility +module provides that a label given to the \opt{label} option gets set with +both a regular \cs{label} and a \cs{zlabel}, so that we can refer to it with +both referencing systems. Setting labels for specific lines of the +environment can be done with \cs{zlabel} directly, subject to the same +escaping as for the standard \cs{label}. For more details, see the +description of the \opt{listings} compatibility module at +\zcref{sec:comp-modules}. + +\begin{zchowto}[caption={\pkg{listings}},label={how:listings},escapeinside=`'] +\documentclass{article} +\usepackage{listings} +\usepackage{zref-clever} +\usepackage{hyperref} +\begin{document} +\section{Section 1} +\lstset{escapeinside={(*@}{@*)}, numbers=left, numberstyle=\tiny} +\begin{lstlisting}[caption={Useless code}, label=lst:1] + for i:=maxint to 0 do + begin + { do nothing }(*@\zlabel{ln:1.1}@*) + end; +\end{lstlisting} +\zcref{lst:1, ln:1.1} +\end{document} +\end{zchowto} + + +\subsection{\pkg{enumitem}} + +\zctask{Setup a custom enumerate environment created with \pkg{enumitem} to be + referred to with \cs{zcref}.} + +Since the \texttt{enumerate} environment's counters are reset at each nesting +level, but not with the standard machinery, we have to inform +\pkg{zref-clever} of this resetting behavior with the \opt{counterresetby} +option. Also, given the naming of the underlying counters is tied with the +environment's name and the level's number, we cannot really rely on an +implicit counter-type association, and have to set it explicitly with the +\opt{countertype} option. + +\begin{zchowto}[caption={\pkg{enumitem}}] +\documentclass{article} +\usepackage{zref-clever} +\zcsetup{ + countertype = { + myenumeratei = item , + myenumerateii = item , + myenumerateiii = item , + myenumerateiv = item , + } , + counterresetby = { + myenumerateii = myenumeratei , + myenumerateiii = myenumerateii , + myenumerateiv = myenumerateiii , + } +} +\usepackage{enumitem} +\newlist{myenumerate}{enumerate}{4} +\setlist[myenumerate,1]{label=(\arabic*)} +\setlist[myenumerate,2]{label=(\Roman*)} +\setlist[myenumerate,3]{label=(\Alph*)} +\setlist[myenumerate,4]{label=(\roman*)} +\begin{document} +\begin{myenumerate} +\item An item.\zlabel{item-1} + \begin{myenumerate} + \item An item.\zlabel{item-2} + \begin{myenumerate} + \item An item.\zlabel{item-3} + \begin{myenumerate} + \item An item.\zlabel{item-4} + \end{myenumerate} + \end{myenumerate} + \end{myenumerate} +\end{myenumerate} +\zcref{item-1, item-2, item-3, item-4} +\end{document} +\end{zchowto} + + +\subsection{\pkg{zref-xr}} + +\zctask{Make references to labels set in an external document with + \cs{zcref}.} + +\pkg{zref} itself offers this functionality with module \pkg{zref-xr}, and +\pkg{zref-clever} is prepared to make use of it. Just a couple of details +have to be taken care of, for it to work as intended: i) \pkg{zref-clever} +must be loaded in both the main document and the external document, so that +the imported labels also contain the properties required by \pkg{zref-clever}; +ii) since \cs{zexternaldocument} defines any properties it finds in the labels +from the external document when it imports them, it must be called after +\pkg{zref-clever} is loaded, otherwise the later will find its own internal +properties already defined when it does get loaded, and will justifiably +complain. Note as well that the starred version of \cs{zexternaldocument*}, +which imports the standard labels from the external document, is not +sufficient for \pkg{zref-clever}, since the imported labels will not contain +all the required properties. + +Assuming here \file{documentA.tex} as the main file and \file{documentB.tex} +as the external one, and also assuming we just want to refer in ``\texttt{A}'' +to the labels from ``\texttt{B}'', and not the contrary, a minimum setup would +be the following. + + +\begin{zchowto}[caption={\pkg{zref-xr}},escapeinside=`'] +`\hspace*{-1em}\file{documentA.tex}:\vspace{1ex}' +\documentclass{article} +\usepackage{zref-clever} +\usepackage{zref-xr} +\zexternaldocument[B-]{documentB} +\usepackage{hyperref} +\begin{document} +\section{Section A1} +\zlabel{sec:section-a1} +\zcref{sec:section-a1, B-sec:section-b1} +\end{document} +`\vspace{-1ex}' +`\hspace*{-1em}\file{documentB.tex}:\vspace{1ex}' +\documentclass{article} +\usepackage{zref-clever} +\usepackage{hyperref} +\begin{document} +\section{Section B1} +\zlabel{sec:section-b1} +\end{document} +\end{zchowto} + +\section{Compatibility} +\zlabel{sec:compatibility} + +\subsection{Limitations} +\zlabel{sec:limitations} + +Being based on \pkg{zref} entails one quite sizable advantage for +\pkg{zref-clever}: the extensible referencing system of the former allows +\pkg{zref-clever} to store and retrieve the information it needs to work +without having to redefine some core \LaTeX{} commands. This alone makes for +reduced compatibility problems and less load order issues than the average +package in this functionality area. On the other hand, being based on +\pkg{zref} also does impair the supported scope of \pkg{zref-clever}. Not +because of any particular limitation of either, but because any class or +package which implements some special handling for reference labels +universally does so aiming at the standard referencing system, and whether +specific support for \pkg{zref} is included, or whether things work by +spillover of the particular technique employed, is not guaranteed. + +The limitation here is less one of \pkg{zref-clever} than that of a potencial +lack of support for \pkg{zref} itself. Broadly speaking, what +\pkg{zref-clever} does is setup \pkg{zref} so that its \cs{zref@newlabel}s +contains the information we need using \pkg{zref}'s API. Once the \cs{zlabel} +is set correctly, there is little in the way of \pkg{zref-clever}, it can just +extract the label's information, again using \pkg{zref}'s API, and do its job. +Therefore, the problems that may arise are really in \emph{label setting}. + +For \cs{zlabel} to be able to set a label with everything \pkg{zref-clever} +needs, some conditions must be fulfilled, most of which are pretty much the +same as that of a regular label, but not only. As far as my experience goes, +the following label setting requirements can be potentially problematic and +are not necessarily granted for \cs{zlabel}: + +\begin{enumerate} +\item One must be able to call \cs{zlabel}, directly or indirectly, at the + appropriate scope/location so as to set the label. +\item When \cs{zlabel} is set, it must see a correct value of + \cs{@currentcounter}. +\end{enumerate} + +As to the first, it is not everywhere we technically can set a (z)label. On +verbatim-like environments it depends on how they are defined and whether they +provide a proper place or option to do so. But other places may be +problematic too, for example, \pkg{amsmath} display math environments also +handle \cs{label} specially and the same work is not done for \cs{zlabel}. + +Regarding the second, a correctly set \cs{@currentcounter} is critical for the +task of \pkg{zref-clever}: the reference type will depend on that and, +consequently, sorting and compression as well, counter resetting behavior +information is also retrieved based on it, and so on. Since the 2020-10-01 +\LaTeX{} release, \cs{@currentcounter} is set by \cs{refstepcounter} alongside +\cs{@currentlabel} and, since the 2021-11-15 release, the support for +\cs{@currentcounter} has been further extended in the kernel. Hence, as long +as kernel features are involved, or as long as \cs{refstepcounter} is the tool +used for the purpose of reference setting, \cs{zlabel} will tend to have all +information within its grasp at label setting time. But that's not always the +case. For this reason, \pkg{zref-clever} has the option \opt{currentcounter} +which at least allows for some viable work-arounds when the value of +\cs{@currentcounter} cannot be relied upon. Whether we have a proper opening +to set it, depends on the case. Still, \cs{refstepcounter} is ubiquitous +enough a tool that we can count on \cs{@currentcounter} most of the time. + +All in all, most things work, but some things don't. And if the later will +eventually work depends essentially on whether support for \pkg{zref} is +provided by the relevant packages and classes or not. Or, failing that, +whether \pkg{zref-clever} is able to provide some specific support when a +reasonable way to do so is within reach. + + +\subsection{Compatibility modules} +\zlabel{sec:comp-modules} + +This section gives a description of each compatibility module provided by +\pkg{zref-clever}. These modules intend to smooth the interaction of \LaTeX{} +features, document classes, and packages with \pkg{zref-clever} and +\pkg{zref}, and they can be selectively or completely disabled with the option +\opt{nocompat} (see \zcref{sec:options}). This set is not to be confused with +``the list of packages or classes supported by \pkg{zref-clever}''. In most +circumstances, things should just work out of the box, and need no specific +handling. These are just the ones for which some special treatment was +required. Of course, this effort is bound to be incomplete (see +\zcref{sec:limitations}). + +The purpose of outlining to some extend what the compatibility modules do is +twofold. First, some of them require usage adjustments for label setting, +which must be somehow conveyed in this documentation. Second, the kind and +degree of intervention in external code varies significantly for each module, +and since this is an area of potential friction, a minimum of information for +the users to judge whether they want to leave these modules enabled or not is +due. For this reason, this is also a little technical, but for full details, +see the code documentation. + +\bigskip{} + +\DescribeOption{appendix} % +The \cs{appendix} command provided by many document classes is normally used +to change the behavior of the sectioning commands after that point. Usually, +depending on the class, the changes that interest us involve using \cs{@Alph} +for numbering and \cs{appendixname} for chapter's names. In sum, we'd like to +refer to the appendix sectioning commands as ``appendices'' rather than +``chapters'' or ``sections''. Since the sectioning commands are the same as +before \cs{appendix}, and so are their underlying counters, we must configure +the counter type of the sectioning counters to \texttt{appendix}. And this is +what this compatibility module does, and it uses a \pkg{ltcmdhooks} hook on +\cs{appendix} for the purpose. Hence, this module applies to any document +class or package which provides that command. + +\DescribeOption{appendices} % +This module implements support for the \env{appendices} and +\env{subappendices} environments provided by the \pkg{appendix} package, and +also by \cls{memoir}. The task is the same as for the \texttt{appendix} +module: set proper counter types for the sectioning counters. This module +employs environment hooks to \env{appendices} and \env{subappendices} and a +command hook to \cs{appendix} for the purpose. + +\DescribeOption{memoir} % +The \cls{memoir} class implements several features with one or another +implication for cross-referencing, usually bearing just the standard +referencing system in mind, and related mainly to captions, subfloats, and +notes. This compatibility module tries to adjust \pkg{zref-clever} to these +features with support for the following: i) set counter types for counters +\texttt{subfigure}, \texttt{subtable}, and \texttt{poemline} (used in the +\env{verse} environment); ii) configure resetting behavior +(\opt{counterresetby} option) for \texttt{subfigure} and \texttt{subtable} +counters; iii) provide that the \meta{label} arguments to environments +\env{sidecaption} and \env{sidecontcaption} and commands \cs{bitwonumcaption}, +\cs{bionenumcaption}, and \cs{bicaption} \emph{also} set a \cs{zlabel} of the +same name; iv) provide the \pkg{zref} property ``\texttt{subcaption}'' so that +we can refer to, for example, \texttt{\cs{zcref}[ref=subcaption]\{subcap-1\}} +to emulate the functionality of \cls{memoir}'s \cs{subcaptionref}; v) provide +that \cs{footnote}, \cs{verbfootnote}, \cs{sidefootnote}, and \cs{pagenote} +get a proper \opt{currentcounter} set; and v) set counter types for counters +\texttt{sidefootnote} and \texttt{pagenote}. Naturally, the sheer number of +features that required some specific support implies that some gymnastics were +needed here. But the most sensitive changes are: i) a local redefinition of +\cs{label} inside the environments \env{sidecaption} and \env{sidecontcaption} +and the commands \cs{bitwonumcaption}, \cs{bionenumcaption}, and +\cs{bicaption}; and ii) the use of \pkg{ltcmdhooks} command hooks on +\cs{bitwonumcaption}, \cs{bionenumcaption}, \cs{bicaption}, +\cs{@memsubcaption}, \cs{@makefntext}, and \cs{@makesidefntext}. + +\DescribeOption{KOMA} % +The \cls{KOMA-Script} document classes are much more strict than \cls{memoir} +in using standard mechanisms for cross-reference related features, so that +very little adjustment is needed here. Only the environments +\env{captionbeside} and \env{captionofbeside} require special treatment. And, +though they do use \cs{refstepcounter} under the hood, since they are +environments, we don't get to see reference variables outside them. +\cs{@currentlabel} is smuggled out of the group, but not \cs{@currentcounter}, +so we must arrange for the later to have a correct value outside the caption +environments too. Environment hooks are used for the purpose, essentially +setting \cs{@currentcounter} to \cs{@captype}, which would be the value the +captioning infrastructure would set for it. + +\DescribeOption{amsmath} % +\pkg{amsmath}'s display math environments have their contents processed twice, +once for measuring and the second does the final typesetting. Hence, +\pkg{amsmath} needs to handle \cs{label} specially inside these environments, +otherwise we'd have duplicate labels all around, and indeed it does redefine +\cs{label} locally inside them. Alas, the same treatment is not granted to +\cs{zlabel}. However, \cs{label} is set basically to \emph{store} the value +of the argument inside the environments, and its global meaning is kept in +\cs{ltx@label} which is called at the appropriate time to actually set the +label. So, what \pkg{zref-clever} does is redefine \cs{ltx@label} to set +\texttt{both} a regular \cs{label} and a \cs{zlabel} for the same \meta{label} +(which does not generate a duplicate label problem since the referencing +systems are independent). Therefore, you must use \cs{label} (not +\cs{zlabel}) inside \pkg{amsmath}'s display math environments, and this +compatibility module arranges that you can also refer to that label with +\pkg{zref} and, thus, with \cs{zcref} as well. The following environments are +subject to this usage restriction: \env{equation}, \env{align}, \env{alignat}, +\env{flalign}, \env{xalignat}, \env{gather}, \env{multline}, and their +respective starred versions. In particular, the same is not the case for the +\env{subequations} environment, inside which \cs{zlabel} works as usual (to +refer to the main equation number, that is, right after +\texttt{\cs{begin}\{subequations\}}). See the \zcref{how:amsmath} for an +usage example. The module also ensures proper \opt{currentcounter} values are +in place for the display math environments, for which it uses environment +hooks, and sets the font of equation references to \cs{upshape}, following +\pkg{amsmath}'s \cs{eqref}. Note, however, that \pkg{zref-clever} is not the +only package to redefine \cs{ltx@label}, and compatibility problems may arise +if this module is used with such packages or with document classes that do the +same. In case of trouble, you can load \pkg{zref-clever} with option +\texttt{nocompat=amsmath} and either use the standard referencing system's +facilities to refer to \pkg{amsmath}'s equations or check the code +documentation for the technique used for this (which is pretty standard) and +adapt it to your case. Given that any trouble that may arise here is one of +the proper ``timing'' of the redefinition, it should not be particularly +complicated to make such adjustments. + +\DescribeOption{mathtools} % +\pkg{mathtools} has a feature to show the numbers only for those equations +actually referenced (with \cs{eqref} or \cs{refeq}), which is enabled by the +\opt{showonlyrefs} option. This compatibility module adds support for this +feature, such that equation references made with \cs{zcref} also get marked as +``referenced'' for \pkg{mathtools}, when the option is active, of course. The +module uses a couple of \pkg{mathtools} functions, but does not need to +redefine or hook into anything, everything is handled on \pkg{zref-clever}'s +side. + +\DescribeOption{breqn} % +This compatibility module only sets proper \opt{currentcounter} values for the +environments \env{dgroup}, \env{dmath}, \env{dseries}, and \env{darray}, and +uses environment hooks for the purpose. Note that these environments offer a +\opt{label} option for label setting, but implements it in a way that is +somewhat tricky to grab for our purposes, so we don't do it. However, +\pkg{breqn}'s documentation says the following about the use of \cs{label} +inside its environments: \textquote{Use of the normal \cs{label} command + instead of the \opt{label} option works, I think, most of the time + (untested)}. My light testing suggests the same is true for \cs{zlabel}, +which can then be used directly in these environments. But the ``second +class'' status for this use is the one granted by \pkg{breqn}, there's not +much we can do here. If you have any trouble with this, you may wish to check +\zcref{wkrnd:breqn}. + +\DescribeOption{listings} % +Being \env{lstlisting}s environments what they are, one cannot simply place a +label inside them without special treatment. \pkg{listings} arranges to this +by providing a \opt{label} option for setting a label for the whole +environment, and a properly escaped label command inside the environment can +be used to refer to the line number. While the later can also be used to set +a \cs{zlabel} to make line number references, the \opt{label} option is +catered to the standard labels exclusively. Hence, this compatibility module +uses the same label name -- which luckily and atypically is stored in a +variable -- and sets a \cs{zlabel} as well. This is done by using +\pkg{listings}' \texttt{PreInit} hook, se we don't have to redefine or tamper +with anything for the purpose. Besides this, the module also sets appropriate +\opt{countertype}, \opt{counterresetby} and \opt{currentcounter} values for +the \pkg{listings}' counters: \texttt{lstlisting} and \texttt{lstnumber}. See +the \zcref{how:listings} for an usage example. + +\DescribeOption{enumitem} % +\LaTeX{}'s \env{enumerate} environment requires some special treatment from +\pkg{zref-clever}, since its resetting behavior is not stored in the standard +way, and the counters' names, given they are numbered by level, do not map to +the reference type naturally. This is done by default for the up to four +levels of nested \env{enumerate} environments the kernel offers. +\pkg{enumitem}, though, allows one to increase this maximum list depth for +\env{enumerate} and, if this is done, setup for these deeper nesting levels +have also to be taken care of, and that's what this compatibility module does. +All settings here are internal to \pkg{zref-clever}, no hooks or redefinitions +are needed, we just check the existing pertinent counters at +\texttt{begindocument}, and supply settings for them. Of course, this means +that only \pkg{enumitem}'s settings done in the preamble will be visible to +the module and provided for. + +\DescribeOption{subcaption} % +This compatibility module sets appropriate \opt{countertype} and +\opt{counterresetby} for the \texttt{subfigure} and \texttt{subtable} +counters, and provides the \pkg{zref} property ``\texttt{subref}'' so that we +can refer to, for example, \texttt{\cs{zcref}[ref=subref]\{\meta{label}\}} to +emulate the functionality of \cls{subcaption}'s \cs{subref}. The later +feature uses the \cs{caption@subtypehook} provided by \pkg{caption} to locally +add the \texttt{subref} property to \pkg{zref}'s main property list. + +\DescribeOption{subfig} % +This module just sets appropriate \opt{countertype} and \opt{counterresetby} +for the \texttt{subfigure} and \texttt{subtable} counters. + + +\subsection{Work-arounds} + +\marginpar{\raggedleft\raisebox{-1.5ex}{\dbend}}As should be clear by now, the +use of \pkg{zref}'s \cs{zlabel} and thus of \pkg{zref-clever} may occasionally +require some adjustments, since it does not enjoy the universal support the +standard referencing system does. The compatibility modules presented in +\zcref{sec:comp-modules} go a long way in ensuring the user has to worry very +little about it, but they cannot hopefully go all the way. Not only because +this kind of support will never be exhaustive, but also since, sometimes, +given the way certain features are implemented by packages or document +classes, there may not be a reasonable way to provide this support, from our +side. But, still, most of the time, it is still ``viable'' to get there, if +one really wishes to do so. So, this section keeps track of some known +recipes, which I don't think belong in \pkg{zref-clever} itself, but which you +may choose to use. Note that this list is intended to spare users from having +to reinvent the wheel every time someone needs something of the sort, but from +\pkg{zref-clever}'s perspective, their status is ``not supported''. + + +\subsection*{\pkg{breqn}} + +As mentioned in \opt{breqn}'s compatibility module (\zcref{sec:comp-modules}), +\pkg{breqn}'s math environments \env{dgroup}, \env{dmath}, \env{dseries}, and +\env{darray} offer a \opt{label} option (plus \opt{labelprefix}) for the +purpose of label setting. Setting a \cs{zlabel} alongside with a regular +\cs{label} based on that option requires redefining some of \pkg{breqn} +internals. Also, \pkg{breqn} does not use \cs{refstepcounter} to increment +the equation counters and, as a result, fails to set \pkg{hyperref} anchors +for the equations (thus affecting standard labels too). The example below +also provides to that.\footnote{The later work-around thanks to Heiko + Oberdiek, at \url{https://tex.stackexchange.com/a/241150}.} + + +\begin{zcworkaround}[caption={\pkg{breqn}},label={wkrnd:breqn}] +\documentclass{article} +\usepackage{zref-clever} +\usepackage{breqn} +\makeatletter +\define@key{breqn}{label}{% + \edef\next@label{% + \noexpand\label{\next@label@pre#1}% + \noexpand\zlabel{\next@label@pre#1}}% + \let\next@label@pre\@empty} +\makeatother +\usepackage{hyperref} +\usepackage{etoolbox} +\makeatletter +\patchcmd\eq@setnumber{\stepcounter}{\refstepcounter}{}{% + \errmessage{Patching \noexpand\eq@setnumber failed}} +\makeatother +\begin{document} +\section{Section 1} +\begin{dmath}[label={eq:1}] + f(x)=\frac{1}{x} \condition{for $x\neq 0$} +\end{dmath} +\begin{dmath}[labelprefix={eq:},label={2}] + H_2^2 = x_1^2 + x_1 x_2 + x_2^2 - q_1 - q_2 +\end{dmath} +\zcref{eq:1, eq:2} +\end{document} +\end{zcworkaround} + +Of course, you can always adapt things to your needs and, e.g., make the +\opt{label} option set just \cs{zlabel} instead of both labels, or create a +separate \opt{zlabel} option. + + +\section{Acknowledgments} + +\pkg{zref-clever} would not be possible without other people's previous work +and help. + +Heiko Oberdiek's \pkg{zref}, now maintained by the Oberdiek Package Support +Group, is the underlying infrastructure of this package. The potential of its +basic concept and the solid implementation were certainly among the reasons +I've chosen to venture into these waters, to start with. And I believe they +will remain one of the main assets of \pkg{zref-clever} as it matures. + +The name of the package makes no secret that a major inspiration for the kind +of ``feel'' I strove to achieve has been Toby Cubitt's \pkg{cleveref}. +Indeed, I have been an user of \pkg{cleveref} for several years, and a happy +one at that. But the role \pkg{cleveref} played in the development of +\pkg{zref-clever} extends beyond the visible influence in the design of user +facing functionality. Some technical solutions and, specially, the handling +of support for other packages were a valuable reference. Hence, the +accumulated experience of \pkg{cleveref} allowed for \pkg{zref-clever} to +start on a more solid foundation than would otherwise be the case. + +The long term efforts of the \LaTeX3 \cs{Team} around \pkg{expl3} and +\pkg{xparse} have also left their marks in this package. By implementing +powerful tools and smoothing several regular programming tasks, they have +certainly reduced my entry barrier to \LaTeX{} programming and enabled me to +develop this package with a significantly reduced effort. And, given the +constraints of my abilities, the result is no doubt much better than it would +be in their absence. + +Besides these more general acknowledgments, a number of people have +contributed to \pkg{zref-clever}, whether they are aware of it or not. +Suggestions, ideas, solutions to problems, bug reports or even encouragement +were generously provided by: Ulrike Fischer, Frank Mittelbach, Phelype +Oleinik, Jonathan P.\ Spratte, Enrico Gregorio, Steven B.\ Segletes, +\texttt{@samcarter}, Alan Munn, Florent Rougon, and David Carlisle. + +If I have inadvertently left anyone off the list I apologize, and please let +me know, so that I can correct the oversight. + +Thank you all very much! + + +\section{Change history} + +A change log with relevant changes for each version, eventual upgrade +instructions, and upcoming changes, is maintained in the package's repository, +at \url{https://github.com/gusbrs/zref-clever/blob/main/CHANGELOG.md}. An +archive of historical versions of the package is also kept at +\url{https://github.com/gusbrs/zref-clever/releases}. + +\end{document} diff --git a/Master/texmf-dist/source/latex/zref-clever/zref-clever.dtx b/Master/texmf-dist/source/latex/zref-clever/zref-clever.dtx new file mode 100644 index 00000000000..024aa50a991 --- /dev/null +++ b/Master/texmf-dist/source/latex/zref-clever/zref-clever.dtx @@ -0,0 +1,7161 @@ +% \iffalse meta-comment +% +% File: zref-clever.dtx +% +% This file is part of the LaTeX package "zref-clever". +% +% Copyright (C) 2021 Gustavo Barros +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file: +% +% https://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 is "maintained" (as per LPPL maintenance status) by +% Gustavo Barros. +% +% This work consists of the files zref-clever.dtx, +% zref-clever.ins, +% zref-clever.tex, +% zref-clever-code.tex, +% and the derived files listed in MANIFEST.md. +% +% The released version of this package is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the package can be found at +% +% https://github.com/gusbrs/zref-clever +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +% \fi +% +% \iffalse +%<*driver> +\documentclass{l3doc} + +% Have \GetFileInfo pick up date and version data and used in the +% documentation. +\usepackage[cap,nameinlink=false,check,titleref]{zref-clever} + +\begin{document} + +\DocInput{zref-clever.dtx} + +\end{document} +% +% \fi +% +% \DoNotIndex{\\,\{,\}} +% \DoNotIndex{\c@,\cl@,\c@enumN,\p@} +% \DoNotIndex{\the} +% +% +% \NewDocumentCommand\opt{m}{\texttt{#1}} +% +% \pdfstringdefDisableCommands{% +% \def\opt#1{#1} +% } +% +% ^^A Have the Index at 'section' level rather than 'part'. Otherwise it is +% ^^A just the same definition from 'l3doc.cls'. +% \IndexPrologue{% +% \section*{Index} +% \markboth{Index}{Index} +% \addcontentsline{toc}{section}{Index} +% The italic numbers denote the pages where the corresponding entry is +% described, numbers underlined point to the definition, all others indicate +% the places where it is used.% +% } +% +% +% \GetFileInfo{zref-clever.sty} +% +% \title{% +% The \pkg{zref-clever} package implementation% +% \thanks{This file describes \fileversion, released \filedate.}% +% } +% +% \author{% +% Gustavo Barros% +% \thanks{\url{https://github.com/gusbrs/zref-clever}}% +% } +% +% \date{\filedate} +% +% \maketitle +% +% \tableofcontents +% +% +% \section{Initial setup} +% +% Start the \pkg{DocStrip} guards. +% \begin{macrocode} +%<*package> +% \end{macrocode} +% +% Identify the internal prefix (\LaTeX3 \pkg{DocStrip} convention). +% \begin{macrocode} +%<@@=zrefclever> +% \end{macrocode} +% +% Taking a stance on backward compatibility of the package. During initial +% development, we have used freely recent features of the kernel (albeit +% refraining from \pkg{l3candidates}, even though I'd have loved to have used +% \cs{bool_case_true:}\dots{}). We presume \pkg{xparse} (which made to the +% kernel in the 2020-10-01 release), and \pkg{expl3} as well (which made to +% the kernel in the 2020-02-02 release). We also just use UTF-8 for the +% dictionaries (which became the default input encoding in the 2018-04-01 +% release). Finally, a couple of changes came with the 2021-11-15 kernel +% release, which are important here. First, a fix was made to the new hook +% management system (\pkg{ltcmdhooks}), with implications to the hook we add +% to \cs{appendix} (see \url{https://tex.stackexchange.com/q/617905} and +% \url{https://github.com/latex3/latex2e/pull/699}, thanks Phelype Oleinik). +% Second, the support for \cs{@currentcounter} has been improved, including +% \cs{footnote} and \pkg{amsmath} (see +% \url{https://github.com/latex3/latex2e/issues/687}, thanks Frank Mittelbach +% and Ulrike Fischer). Hence, since we would not be able to go much backwards +% without special handling anyway, we make the cut at the 2021-11-15 kernel +% release. +% +% \begin{macrocode} +\providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} +\IfFormatAtLeastTF{2021-11-15} + {} + {% + \PackageError{zref-clever}{LaTeX kernel too old} + {% + 'zref-clever' requires a LaTeX kernel 2021-11-15 or newer.% + \MessageBreak Loading will abort!% + }% + \endinput + }% +% \end{macrocode} +% +% +% Identify the package. +% \begin{macrocode} +\ProvidesExplPackage {zref-clever} {2021-11-24} {0.1.0-alpha} + {Clever LaTeX cross-references based on zref} +% \end{macrocode} +% +% +% \section{Dependencies} +% +% Required packages. Besides these, \pkg{zref-hyperref}, \pkg{zref-titleref}, +% and \pkg{zref-check} may also be loaded depending on user options. +% +% \begin{macrocode} +\RequirePackage { zref-base } +\RequirePackage { zref-user } +\RequirePackage { zref-abspage } +\RequirePackage { l3keys2e } +\RequirePackage { ifdraft } +% \end{macrocode} +% +% +% \section{\pkg{zref} setup} +% +% For the purposes of the package, we need to store some information with the +% labels, some of it standard, some of it not so much. So, we have to setup +% \pkg{zref} to do so. +% +% Some basic properties are handled by \pkg{zref} itself, or some of its +% modules. The \texttt{default} and \texttt{page} properties are provided by +% \pkg{zref-base}, while \pkg{zref-abspage} provides the \texttt{abspage} +% property which gives us a safe and easy way to sort labels for page +% references. +% +% The \texttt{counter} property, in most cases, will be just the kernel's +% \cs{@currentcounter}, set by \cs{refstepcounter}. However, not everywhere +% is it assured that \cs{@currentcounter} gets updated as it should, so we +% need to have some means to manually tell \pkg{zref-clever} what the current +% counter actually is. This is done with the \opt{currentcounter} option, and +% stored in \cs{l_@@_current_counter_tl}, whose default is +% \cs{@currentcounter}. +% +% \begin{macrocode} +\zref@newprop { zc@counter } { \l_@@_current_counter_tl } +\zref@addprop \ZREF@mainlist { zc@counter } +% \end{macrocode} +% +% The reference itself, stored by \pkg{zref-base} in the \texttt{default} +% property, is somewhat a disputed real estate. In particular, the use of +% \cs{labelformat} (previously from \pkg{varioref}, now in the kernel) will +% include there the reference ``prefix'' and complicate the job we are trying +% to do here. Hence, we isolate \cs[no-index]{the}\meta{counter} and store it +% ``clean'' in \texttt{thecounter} for reserved use. Since +% \cs{@currentlabel}, which populates the \texttt{default} property, is +% \emph{more reliable} than \cs{@currentcounter}, \texttt{thecounter} is meant +% to be kept as an \emph{option} (\opt{ref} option), in case there's need to +% use \pkg{zref-clever} together with \cs{labelformat}. Based on the +% definition of \cs{@currentlabel} done inside \cs{refstepcounter} in `texdoc +% source2e', section `ltxref.dtx'. We just drop the \cs[no-index]{p@...} +% prefix. +% +% \begin{macrocode} +\zref@newprop { thecounter } + { + \cs_if_exist:cTF { c@ \l_@@_current_counter_tl } + { \use:c { the \l_@@_current_counter_tl } } + { + \cs_if_exist:cT { c@ \@currentcounter } + { \use:c { the \@currentcounter } } + } + } +\zref@addprop \ZREF@mainlist { thecounter } +% \end{macrocode} +% +% +% Much of the work of \pkg{zref-clever} relies on the association between a +% label's ``counter'' and its ``type'' (see the User manual section on +% ``Reference types''). Superficially examined, one might think this relation +% could just be stored in a global property list, rather than in the label +% itself. However, there are cases in which we want to distinguish different +% types for the same counter, depending on the document context. Hence, we +% need to store the ``type'' of the ``counter'' for each ``label''. In +% setting this, the presumption is that the label's type has the same name as +% its counter, unless it is specified otherwise by the \opt{countertype} +% option, as stored in \cs{l_@@_counter_type_prop}. +% +% \begin{macrocode} +\zref@newprop { zc@type } + { + \exp_args:NNe \prop_if_in:NnTF \l_@@_counter_type_prop + \l_@@_current_counter_tl + { + \exp_args:NNe \prop_item:Nn \l_@@_counter_type_prop + { \l_@@_current_counter_tl } + } + { \l_@@_current_counter_tl } + } +\zref@addprop \ZREF@mainlist { zc@type } +% \end{macrocode} +% +% +% Since the \texttt{default}/\texttt{thecounter} and \texttt{page} properties +% store the ``\emph{printed} representation'' of their respective counters, +% for sorting and compressing purposes, we are also interested in their +% numeric values. So we store them in \texttt{zc@cntval} and +% \texttt{zc@pgval}. For this, we use \cs[no-index]{c@}\meta{counter}, which +% contains the counter's numerical value (see `texdoc source2e', section +% `ltcounts.dtx'). +% \begin{macrocode} +\zref@newprop { zc@cntval } [0] + { + \cs_if_exist:cTF { c@ \l_@@_current_counter_tl } + { \int_use:c { c@ \l_@@_current_counter_tl } } + { + \cs_if_exist:cT { c@ \@currentcounter } + { \int_use:c { c@ \@currentcounter } } + } + } +\zref@addprop \ZREF@mainlist { zc@cntval } +\zref@newprop* { zc@pgval } [0] { \int_use:c { c@page } } +\zref@addprop \ZREF@mainlist { zc@pgval } +% \end{macrocode} +% +% +% However, since many counters (may) get reset along the document, we require +% more than just their numeric values. We need to know the reset chain of a +% given counter, in order to sort and compress a group of references. Also +% here, the ``printed representation'' is not enough, not only because it is +% easier to work with the numeric values but, given we occasionally group +% multiple counters within a single type, sorting this group requires to know +% the actual counter reset chain. +% +% Furthermore, even if it is true that most of the definitions of counters, +% and hence of their reset behavior, is likely to be defined in the preamble, +% this is not necessarily true. Users can create counters, newtheorems +% mid-document, and alter their reset behavior along the way. Was that not +% the case, we could just store the desired information at +% \texttt{begindocument} in a variable and retrieve it when needed. But since +% it is, we need to store the information with the label, with the values as +% current when the label is set. +% +% Though counters can be reset at any time, and in different ways at that, the +% most important use case is the automatic resetting of counters when some +% other counter is stepped, as performed by the standard mechanisms of the +% kernel (optional argument of \cs{newcounter}, \cs{@addtoreset}, +% \cs{counterwithin}, and related infrastructure). The canonical optional +% argument of \cs{newcounter} establishes that the counter being created (the +% mandatory argument) gets reset every time the ``enclosing counter'' gets +% stepped (this is called in the usual sources ``within-counter'', ``old +% counter'', ``supercounter'', ``parent counter'' etc.). This information is +% somewhat tricky to get. For starters, the counters which may reset the +% current counter are not retrievable from the counter itself, because this +% information is stored with the counter that does the resetting, not with the +% one that gets reset (the list is stored in \cs[no-index]{cl@}\meta{counter} +% with format +% \texttt{\cs{@elt}\{countera\}\cs{@elt}\{counterb\}\cs{@elt}\{counterc\}}, +% see \file{ltcounts.dtx} in \texttt{texdoc source2e}). Besides, there may be +% a chain of resetting counters, which must be taken into account: if +% \texttt{counterC} gets reset by \texttt{counterB}, and \texttt{counterB} +% gets reset by \texttt{counterA}, stepping the latter affects all three of +% them. +% +% The procedure below examines a set of counters, those in +% \cs{l_@@_counter_resetters_seq}, and for each of them retrieves the set of +% counters it resets, as stored in \cs[no-index]{cl@}\meta{counter}, looking +% for the counter for which we are trying to set a label +% (\cs{l_@@_current_counter_tl}, by default \cs{@currentcounter}, passed as an +% argument to the functions). There is one relevant caveat to this procedure: +% \cs{l_@@_counter_resetters_seq} is populated by hand with the ``usual +% suspects'', there is no way (that I know of) to ensure it is exhaustive. +% However, it is not that difficult to create a reasonable ``usual suspects'' +% list which, of course, should include the counters for the sectioning +% commands to start with, and it is easy to add more counters to this list if +% needed, with the option \opt{counterresetters}. Unfortunately, not all +% counters are created alike, or reset alike. Some counters, even some kernel +% ones, get reset by other mechanisms (notably, the \texttt{enumerate} +% environment counters do not use the regular counter machinery for resetting +% on each level, but are nested nevertheless by other means). Therefore, +% inspecting \cs[no-index]{cl@}\meta{counter} cannot possibly fully account +% for all of the automatic counter resetting which takes place in the +% document. And there's also no other ``general rule'' we could grab on for +% this, as far as I know. So we provide a way to manually tell +% \pkg{zref-clever} of these cases, by means of the \opt{counterresetby} +% option, whose information is stored in \cs{l_@@_counter_resetby_prop}. This +% manual specification has precedence over the search through +% \cs{l_@@_counter_resetters_seq}, and should be handled with care, since +% there is no possible verification mechanism for this. +% +% +% \begin{macro}[EXP]{\@@_get_enclosing_counters_value:n} +% Recursively generate a \emph{sequence} of ``enclosing counters'' values, +% for a given \meta{counter} and leave it in the input stream. This +% function must be expandable, since it gets called from \cs{zref@newprop} +% and is the one responsible for generating the desired information when +% the label is being set. Note that the order in which we are getting this +% information is reversed, since we are navigating the counter reset chain +% bottom-up. But it is very hard to do otherwise here where we need +% expandable functions, and easy to handle at the reading side. +% \begin{syntax} +% \cs{@@_get_enclosing_counters_value:n} \Arg{counter} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_get_enclosing_counters_value:n #1 + { + \cs_if_exist:cT { c@ \@@_counter_reset_by:n {#1} } + { + { \int_use:c { c@ \@@_counter_reset_by:n {#1} } } + \@@_get_enclosing_counters_value:e + { \@@_counter_reset_by:n {#1} } + } + } +% \end{macrocode} +% +% Both \texttt{e} and \texttt{f} expansions work for this particular recursive +% call. I'll stay with the \texttt{e} variant, since conceptually it is what +% I want (\texttt{x} itself is not expandable), and this package is anyway not +% compatible with older kernels for which the performance penalty of the +% \texttt{e} expansion would ensue (see also +% \url{https://tex.stackexchange.com/q/611370/#comment1529282_611385}, thanks +% Enrico Gregorio, aka `egreg'). +% \begin{macrocode} +\cs_generate_variant:Nn \@@_get_enclosing_counters_value:n { e } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}[EXP]{\@@_counter_reset_by:n} +% Auxiliary function for \cs{@@_get_enclosing_counters_value:n}, and useful +% on its own standing. It is broken in parts to be able to use the +% expandable mapping functions. \cs{@@_counter_reset_by:n} leaves in the +% stream the ``enclosing counter'' which resets \meta{counter}. +% \begin{syntax} +% \cs{@@_counter_reset_by:n} \Arg{counter} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_counter_reset_by:n #1 + { + \bool_if:nTF + { \prop_if_in_p:Nn \l_@@_counter_resetby_prop {#1} } + { \prop_item:Nn \l_@@_counter_resetby_prop {#1} } + { + \seq_map_tokens:Nn \l_@@_counter_resetters_seq + { \@@_counter_reset_by_aux:nn {#1} } + } + } +\cs_new:Npn \@@_counter_reset_by_aux:nn #1#2 + { + \cs_if_exist:cT { c@ #2 } + { + \tl_if_empty:cF { cl@ #2 } + { + \tl_map_tokens:cn { cl@ #2 } + { \@@_counter_reset_by_auxi:nnn {#2} {#1} } + } + } + } +\cs_new:Npn \@@_counter_reset_by_auxi:nnn #1#2#3 + { + \str_if_eq:nnT {#2} {#3} + { \tl_map_break:n { \seq_map_break:n {#1} } } + } +% \end{macrocode} +% \end{macro} +% +% +% Finally, we create the \texttt{zc@enclval} property, and add it to the +% \texttt{main} property list. +% \begin{macrocode} +\zref@newprop { zc@enclval } + { + \@@_get_enclosing_counters_value:e + \l_@@_current_counter_tl + } +\zref@addprop \ZREF@mainlist { zc@enclval } +% \end{macrocode} +% +% +% Another piece of information we need is the page numbering format being used +% by \cs{thepage}, so that we know when we can (or not) group a set of page +% references in a range. Unfortunately, \texttt{page} is not a typical +% counter in ways which complicates things. First, it does commonly get reset +% along the document, not necessarily by the usual counter reset chains, but +% rather with \cs{pagenumbering} or variations thereof. Second, the format of +% the page number commonly changes in the document (roman, arabic, etc.), not +% necessarily, though usually, together with a reset. Trying to ``parse'' +% \cs{thepage} to retrieve such information is bound to go wrong: we don't +% know, and can't know, what is within that macro, and that's the business of +% the user, or of the documentclass, or of the loaded packages. The technique +% used by \pkg{cleveref}, which we borrow here, is simple and smart: store +% with the label what \cs{thepage} would return, if the counter \cs{c@page} +% was ``\(1\)''. That does not allow us to \emph{sort} the references, +% luckily however, we have \texttt{abspage} which solves this problem. But we +% can decide whether two labels can be compressed into a range or not based on +% this format: if they are identical, we can compress them, otherwise, we +% can't. To do so, we locally redefine \cs{c@page} to return ``1'', thus +% avoiding any global spillovers of this trick. Since this operation is not +% expandable we cannot run it directly from the property definition. Hence, +% we use a shipout hook, and set \cs{g_@@_page_format_tl}, which can then be +% retrieved by the starred definition of +% \texttt{\cs{zref@newprop}*\{zc@pgfmt\}}. +% +% \begin{macrocode} +\tl_new:N \g_@@_page_format_tl +\cs_new_protected:Npx \@@_page_format_aux: { \int_eval:n { 1 } } +\AddToHook { shipout / before } + { + \group_begin: + \cs_set_eq:NN \c@page \@@_page_format_aux: + \tl_gset:Nx \g_@@_page_format_tl { \thepage } + \group_end: + } +\zref@newprop* { zc@pgfmt } { \g_@@_page_format_tl } +\zref@addprop \ZREF@mainlist { zc@pgfmt } +% \end{macrocode} +% +% +% Still some other properties which we don't need to handle at the data +% provision side, but need to cater for at the retrieval side, are the ones +% from the \pkg{zref-xr} module, which are added to the labels imported from +% external documents, and needed to construct hyperlinks to them and to +% distinguish them from the current document ones at sorting and compressing: +% \texttt{urluse}, \texttt{url} and \texttt{externaldocument}. +% +% +% +% \section{Plumbing} +% +% +% \subsection{Auxiliary} +% +% +% \begin{macro} +% { +% \@@_if_package_loaded:n , +% \@@_if_class_loaded:n , +% } +% Just a convenience, since sometimes we just need one of the branches, and +% it is particularly easy to miss the empty F branch after a long T one. +% \begin{macrocode} +\prg_new_conditional:Npnn \@@_if_package_loaded:n #1 { T , F , TF } + { \IfPackageLoadedTF {#1} { \prg_return_true: } { \prg_return_false: } } +\prg_new_conditional:Npnn \@@_if_class_loaded:n #1 { T , F , TF } + { \IfClassLoadedTF {#1} { \prg_return_true: } { \prg_return_false: } } +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Messages} +% +% +% \begin{macrocode} +\msg_new:nnn { zref-clever } { option-not-type-specific } + { + Option~'#1'~is~not~type-specific~\msg_line_context:.~ + Set~it~in~'\iow_char:N\\zcLanguageSetup'~before~first~'type'~ + switch~or~as~package~option. + } +\msg_new:nnn { zref-clever } { option-only-type-specific } + { + No~type~specified~for~option~'#1'~\msg_line_context:.~ + Set~it~after~'type'~switch. + } +\msg_new:nnn { zref-clever } { key-requires-value } + { The~'#1'~key~'#2'~requires~a~value~\msg_line_context:. } +\msg_new:nnn { zref-clever } { language-declared } + { Language~'#1'~is~already~declared~\msg_line_context:.~Nothing~to~do. } +\msg_new:nnn { zref-clever } { unknown-language-alias } + { + Language~'#1'~is~unknown~\msg_line_context:.~Can't~alias~to~it.~ + See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ + '\iow_char:N\\zcDeclareLanguageAlias'. + } +\msg_new:nnn { zref-clever } { unknown-language-setup } + { + Language~'#1'~is~unknown~\msg_line_context:.~Can't~set~it~up.~ + See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ + '\iow_char:N\\zcDeclareLanguageAlias'. + } +\msg_new:nnn { zref-clever } { unknown-language-opt } + { + Language~'#1'~is~unknown~\msg_line_context:.~Using~default.~ + See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ + '\iow_char:N\\zcDeclareLanguageAlias'. + } +\msg_new:nnn { zref-clever } { unknown-language-decl } + { + Can't~set~declension~'#1'~for~unknown~language~'#2'~\msg_line_context:.~ + See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ + '\iow_char:N\\zcDeclareLanguageAlias'. + } +\msg_new:nnn { zref-clever } { language-no-decl-ref } + { + Language~'#1'~has~no~declared~declension~cases~\msg_line_context:.~ + Nothing~to~do~with~option~'d=#2'. + } +\msg_new:nnn { zref-clever } { language-no-gender } + { + Language~'#1'~has~no~declared~gender~\msg_line_context:.~ + Nothing~to~do~with~option~'#2=#3'. + } +\msg_new:nnn { zref-clever } { language-no-decl-setup } + { + Language~'#1'~has~no~declared~declension~cases~\msg_line_context:.~ + Nothing~to~do~with~option~'case=#2'. + } +\msg_new:nnn { zref-clever } { unknown-decl-case } + { + Declension~case~'#1'~unknown~for~language~'#2'~\msg_line_context:.~ + Using~default~declension~case. + } +\msg_new:nnn { zref-clever } { nudge-multitype } + { + Reference~with~multiple~types~\msg_line_context:.~ + You~may~wish~to~separate~them~or~review~language~around~it. + } +\msg_new:nnn { zref-clever } { nudge-comptosing } + { + Multiple~labels~have~been~compressed~into~singular~type~name~ + for~type~'#1'~\msg_line_context:. + } +\msg_new:nnn { zref-clever } { nudge-plural-when-sg } + { + Option~'sg'~signals~that~a~singular~type~name~was~expected~ + \msg_line_context:.~But~type~'#1'~has~plural~type~name. + } +\msg_new:nnn { zref-clever } { gender-not-declared } + { Language~'#1'~has~no~'#2'~gender~declared~\msg_line_context:. } +\msg_new:nnn { zref-clever } { nudge-gender-mismatch } + { + Gender~mismatch~for~type~'#1'~\msg_line_context:.~ + You've~specified~'g=#2'~but~type~name~is~'#3'~for~language~'#4'. + } +\msg_new:nnn { zref-clever } { nudge-gender-not-declared-for-type } + { + You've~specified~'g=#1'~\msg_line_context:.~ + But~gender~for~type~'#2'~is~not~declared~for~language~'#3'. + } +\msg_new:nnn { zref-clever } { nudgeif-unknown-value } + { Unknown~value~'#1'~for~'nudgeif'~option~\msg_line_context:. } +\msg_new:nnn { zref-clever } { option-document-only } + { Option~'#1'~is~only~available~after~\iow_char:N\\begin\{document\}. } +\msg_new:nnn { zref-clever } { dict-loaded } + { Loaded~'#1'~dictionary. } +\msg_new:nnn { zref-clever } { dict-not-available } + { Dictionary~for~'#1'~not~available~\msg_line_context:. } +\msg_new:nnn { zref-clever } { unknown-language-load } + { + Language~'#1'~is~unknown~\msg_line_context:.~Unable~to~load~dictionary.~ + See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ + '\iow_char:N\\zcDeclareLanguageAlias'. + } +\msg_new:nnn { zref-clever } { zref-property-undefined } + { + Option~'ref=#1'~requested~\msg_line_context:.~ + But~the~property~'#1'~is~not~declared,~falling-back~to~'default'. + } +\msg_new:nnn { zref-clever } { hyperref-preamble-only } + { + Option~'hyperref'~only~available~in~the~preamble~\msg_line_context:.~ + To~inhibit~hyperlinking~locally,~you~can~use~the~starred~version~of~ + '\iow_char:N\\zcref'. + } +\msg_new:nnn { zref-clever } { missing-hyperref } + { Missing~'hyperref'~package.~Setting~'hyperref=false'. } +\msg_new:nnn { zref-clever } { titleref-preamble-only } + { + Option~'titleref'~only~available~in~the~preamble~\msg_line_context:.~ + Did~you~mean~'ref=title'?. + } +\msg_new:nnn { zref-clever } { option-preamble-only } + { Option~'#1'~only~available~in~the~preamble~\msg_line_context:. } +\msg_new:nnn { zref-clever } { unknown-compat-module } + { + Unknown~compatibility~module~'#1'~given~to~option~'nocompat'.~ + Nothing~to~do. + } +\msg_new:nnn { zref-clever } { missing-zref-check } + { + Option~'check'~requested~\msg_line_context:.~ + But~package~'zref-check'~is~not~loaded,~can't~run~the~checks. + } +\msg_new:nnn { zref-clever } { missing-type } + { Reference~type~undefined~for~label~'#1'~\msg_line_context:. } +\msg_new:nnn { zref-clever } { missing-property } + { Reference~property~'#1'~undefined~for~label~'#2'~\msg_line_context:. } +\msg_new:nnn { zref-clever } { missing-name } + { Reference~format~option~'#1'~undefined~for~type~'#2'~\msg_line_context:. } +\msg_new:nnn { zref-clever } { missing-string } + { + We~couldn't~find~a~value~for~reference~option~'#1'~\msg_line_context:.~ + But~we~should~have:~throw~a~rock~at~the~maintainer. + } +\msg_new:nnn { zref-clever } { single-element-range } + { Range~for~type~'#1'~resulted~in~single~element~\msg_line_context:. } +\msg_new:nnn { zref-clever } { compat-package } + { Loaded~support~for~'#1'~package. } +\msg_new:nnn { zref-clever } { compat-class } + { Loaded~support~for~'#1'~documentclass. } +% \end{macrocode} +% +% +% \subsection{Data extraction} +% +% +% \begin{macro}{\@@_def_extract:Nnnn} +% Extract property \meta{prop} from \meta{label} and sets variable \meta{tl +% var} with extracted value. Ensure \cs{zref@extractdefault} is expanded +% exactly twice, but no further to retrieve the proper value. In case the +% property is not found, set \meta{tl var} with \meta{default}. +% \begin{syntax} +% \cs{@@_def_extract:Nnnn} \Arg{tl val} +% ~~\Arg{label} \Arg{prop} \Arg{default} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_def_extract:Nnnn #1#2#3#4 + { + \exp_args:NNNo \exp_args:NNo \tl_set:Nn #1 + { \zref@extractdefault {#2} {#3} {#4} } + } +\cs_generate_variant:Nn \@@_def_extract:Nnnn { NVnn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_extract_unexp:nnn} +% Extract property \meta{prop} from \meta{label}. Ensure that, in the +% context of an x expansion, \cs{zref@extractdefault} is expanded exactly +% twice, but no further to retrieve the proper value. Thus, this is meant +% to be use in an x expansion context, not in other situations. In case the +% property is not found, leave \meta{default} in the stream. +% \begin{syntax} +% \cs{@@_extract_unexp:nnn}\Arg{label}\Arg{prop}\Arg{default} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_extract_unexp:nnn #1#2#3 + { + \exp_args:NNo \exp_args:No + \exp_not:n { \zref@extractdefault {#1} {#2} {#3} } + } +\cs_generate_variant:Nn \@@_extract_unexp:nnn { Vnn , nvn , Vvn } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_extract:nnn} +% An internal version for \cs{zref@extractdefault}. +% \begin{syntax} +% \cs{@@_extract:nnn}\Arg{label}\Arg{prop}\Arg{default} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_extract:nnn #1#2#3 + { \zref@extractdefault {#1} {#2} {#3} } +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Reference format} +% +% For a general discussion on the precedence rules for reference format +% options, see Section ``Reference format'' in the User manual. Internally, +% these precedence rules are handled / enforced in \cs{@@_get_ref_string:nN}, +% \cs{@@_get_ref_font:nN}, and \cs{@@_type_name_setup:} which are the basic +% functions to retrieve proper values for reference format settings. The +% ``fallback'' settings are stored in \cs{g_@@_fallback_dict_prop}. +% +% +% \begin{macro} +% { +% \l_@@_setup_type_tl , +% \l_@@_dict_language_tl , +% \l_@@_dict_decl_case_tl , +% \l_@@_dict_declension_seq , +% \l_@@_dict_gender_seq , +% } +% Store ``current'' type, language, and declension cases in different places +% for option and translation handling, notably in +% \cs{@@_provide_dictionary:n}, \cs{zcRefTypeSetup}, and +% \cs{zcLanguageSetup}. But also for translations retrieval, in +% \cs{@@_get_type_transl:nnnN} and \cs{@@_get_default_transl:nnN}. +% \begin{macrocode} +\tl_new:N \l_@@_setup_type_tl +\tl_new:N \l_@@_dict_language_tl +\tl_new:N \l_@@_dict_decl_case_tl +\seq_new:N \l_@@_dict_declension_seq +\seq_new:N \l_@@_dict_gender_seq +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro} +% { +% \c_@@_ref_options_necessarily_not_type_specific_seq , +% \c_@@_ref_options_possibly_type_specific_seq , +% \c_@@_ref_options_type_names_seq , +% \c_@@_ref_options_font_seq , +% \c_@@_ref_options_typesetup_seq , +% \c_@@_ref_options_reference_seq , +% } +% Lists of reference format related options in ``categories''. Since +% these options are set in different scopes, and at different places, +% storing the actual lists in centralized variables makes the job not only +% easier later on, but also keeps things consistent. +% \begin{macrocode} +\seq_const_from_clist:Nn + \c_@@_ref_options_necessarily_not_type_specific_seq + { + tpairsep , + tlistsep , + tlastsep , + notesep , + } +\seq_const_from_clist:Nn + \c_@@_ref_options_possibly_type_specific_seq + { + namesep , + pairsep , + listsep , + lastsep , + rangesep , + refpre , + refpos , + } +% \end{macrocode} +% Only ``type names'' are ``necessarily type-specific'', which makes them +% somewhat special on the retrieval side of things. In short, they don't have +% their values queried by \cs{@@_get_ref_string:nN}, but by +% \cs{@@_type_name_setup:}. +% \begin{macrocode} +\seq_const_from_clist:Nn + \c_@@_ref_options_type_names_seq + { + Name-sg , + name-sg , + Name-pl , + name-pl , + Name-sg-ab , + name-sg-ab , + Name-pl-ab , + name-pl-ab , + } +% \end{macrocode} +% \cs{c_@@_ref_options_font_seq} are technically ``possibly type-specific'', +% but are not ``language-specific'', so we separate them. +% \begin{macrocode} +\seq_const_from_clist:Nn + \c_@@_ref_options_font_seq + { + namefont , + reffont , + } +% \end{macrocode} +% And, finally, some combined groups of the above variables, for convenience. +% \begin{macrocode} +\seq_new:N \c_@@_ref_options_typesetup_seq +\seq_gconcat:NNN \c_@@_ref_options_typesetup_seq + \c_@@_ref_options_possibly_type_specific_seq + \c_@@_ref_options_type_names_seq +\seq_gconcat:NNN \c_@@_ref_options_typesetup_seq + \c_@@_ref_options_typesetup_seq + \c_@@_ref_options_font_seq +\seq_new:N \c_@@_ref_options_reference_seq +\seq_gconcat:NNN \c_@@_ref_options_reference_seq + \c_@@_ref_options_necessarily_not_type_specific_seq + \c_@@_ref_options_possibly_type_specific_seq +\seq_gconcat:NNN \c_@@_ref_options_reference_seq + \c_@@_ref_options_reference_seq + \c_@@_ref_options_font_seq +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{Languages} +% +% \begin{macro}{\g_@@_languages_prop} +% Stores the names of known languages and the mapping from ``language name'' +% to ``dictionary name''. Whether or not a language or alias is known to +% \pkg{zref-clever} is decided by its presence in this property list. A +% ``base language'' (loose concept here, meaning just ``the name we gave for +% the dictionary in that particular language'') is just like any other one, +% the only difference is that the ``language name'' happens to be the same +% as the ``dictionary name'', in other words, it is an ``alias to itself''. +% \begin{macrocode} +\prop_new:N \g_@@_languages_prop +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}[int]{\zcDeclareLanguage} +% Declare a new language for use with \pkg{zref-clever}. \meta{language} is +% taken to be both the ``language name'' and the ``dictionary name''. +% \oarg{options} receive a \texttt{k=v} set of options, with three valid +% options. The first, \opt{declension}, takes the noun declension cases +% prefixes for \meta{language} as a comma separated list, whose first +% element is taken to be the default case. The second, \opt{gender}, +% receives the genders for \meta{language} as comma separated list. The +% third, \opt{allcaps}, receives no value, and indicates that for +% \meta{language} all nouns must be capitalized for grammatical reasons, in +% which case, the \opt{cap} option is disregarded for \meta{language}. If +% \meta{language} is already known, just warn. This implies a particular +% restriction regarding \oarg{options}, namely that these options, when +% defined by the package, cannot be redefined by the user. This is +% deliberate, otherwise the built-in dictionaries would become much too +% sensitive to this particular user input, and unnecessarily so. +% \cs{zcDeclareLanguage} is preamble only. +% \begin{syntax} +% \cs{zcDeclareLanguage} \oarg{options} \marg{language} +% \end{syntax} +% \begin{macrocode} +\NewDocumentCommand \zcDeclareLanguage { O { } m } + { + \group_begin: + \tl_if_empty:nF {#2} + { + \prop_if_in:NnTF \g_@@_languages_prop {#2} + { \msg_warning:nnn { zref-clever } { language-declared } {#2} } + { + \prop_gput:Nnn \g_@@_languages_prop {#2} {#2} + \prop_new:c { g_@@_dict_ #2 _prop } + \tl_set:Nn \l_@@_dict_language_tl {#2} + \keys_set:nn { zref-clever / declarelang } {#1} + } + } + \group_end: + } +\@onlypreamble \zcDeclareLanguage +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}[int]{\zcDeclareLanguageAlias} +% Declare \meta{language alias} to be an alias of \meta{aliased language}. +% \meta{aliased language} must be already known to \pkg{zref-clever}, as +% stored in \cs{g_@@_languages_prop}. \cs{zcDeclareLanguageAlias} is +% preamble only. +% \begin{syntax} +% \cs{zcDeclareLanguageAlias} \marg{language alias} \marg{aliased language} +% \end{syntax} +% \begin{macrocode} +\NewDocumentCommand \zcDeclareLanguageAlias { m m } + { + \tl_if_empty:nF {#1} + { + \prop_if_in:NnTF \g_@@_languages_prop {#2} + { + \exp_args:NNnx + \prop_gput:Nnn \g_@@_languages_prop {#1} + { \prop_item:Nn \g_@@_languages_prop {#2} } + } + { \msg_warning:nnn { zref-clever } { unknown-language-alias } {#2} } + } + } +\@onlypreamble \zcDeclareLanguageAlias +% \end{macrocode} +% \end{macro} +% +% +% +% \begin{macrocode} +\keys_define:nn { zref-clever / declarelang } + { + declension .code:n = + { + \prop_gput:cnn + { g_@@_dict_ \l_@@_dict_language_tl _prop } + { declension } {#1} + } , + declension .value_required:n = true , + gender .code:n = + { + \prop_gput:cnn + { g_@@_dict_ \l_@@_dict_language_tl _prop } + { gender } {#1} + } , + gender .value_required:n = true , + allcaps .code:n = + { + \prop_gput:cnn + { g_@@_dict_ \l_@@_dict_language_tl _prop } + { allcaps } { true } + } , + allcaps .value_forbidden:n = true , + } +% \end{macrocode} +% +% +% +% \begin{macro}{\@@_process_language_options:} +% Auxiliary function for \cs{@@_zcref:nnn}, responsible for processing +% options from \cs{zcDeclareLanguage}. It is necessary to separate them +% from the reference options machinery because their behavior is language +% dependent, but the language itself can also be set as an option +% (\opt{lang}, value stored in \cs{l_@@_ref_language_tl}). Hence, we must +% validate these options after the reference options have been set. It is +% expected to be called right (or soon) after \cs{keys_set:nn} in +% \cs{@@_zcref:nnn}, where current values for \cs{l_@@_ref_language_tl} and +% \cs{l_@@_ref_decl_case_tl} are in place. +% \begin{macrocode} +\cs_new_protected:Npn \@@_process_language_options: + { + \exp_args:NNx \prop_get:NnNTF \g_@@_languages_prop + { \l_@@_ref_language_tl } + \l_@@_dict_language_tl + { +% \end{macrocode} +% Validate the declension case (\opt{d}) option against the declared cases for +% the reference language. If the user value for the latter does not match the +% declension cases declared for the former, the function sets an appropriate +% value for \cs{l_@@_ref_decl_case_tl}, either using the default case, or +% clearing the variable, depending on the language setup. And also issues a +% warning about it. +% \begin{macrocode} + \exp_args:NNx \seq_set_from_clist:Nn + \l_@@_dict_declension_seq + { + \prop_item:cn + { + g_@@_dict_ + \l_@@_dict_language_tl _prop + } + { declension } + } + \seq_if_empty:NTF \l_@@_dict_declension_seq + { + \tl_if_empty:NF \l_@@_ref_decl_case_tl + { + \msg_warning:nnxx { zref-clever } + { language-no-decl-ref } + { \l_@@_ref_language_tl } + { \l_@@_ref_decl_case_tl } + \tl_clear:N \l_@@_ref_decl_case_tl + } + } + { + \tl_if_empty:NTF \l_@@_ref_decl_case_tl + { + \seq_get_left:NN \l_@@_dict_declension_seq + \l_@@_ref_decl_case_tl + } + { + \seq_if_in:NVF \l_@@_dict_declension_seq + \l_@@_ref_decl_case_tl + { + \msg_warning:nnxx { zref-clever } + { unknown-decl-case } + { \l_@@_ref_decl_case_tl } + { \l_@@_ref_language_tl } + \seq_get_left:NN \l_@@_dict_declension_seq + \l_@@_ref_decl_case_tl + } + } + } +% \end{macrocode} +% Validate the gender (\opt{g}) option against the declared genders for the +% reference language. If the user value for the latter does not match the +% genders declared for the former, clear \cs{l_@@_ref_gender_tl} and warn. +% \begin{macrocode} + \exp_args:NNx \seq_set_from_clist:Nn + \l_@@_dict_gender_seq + { + \prop_item:cn + { + g_@@_dict_ + \l_@@_dict_language_tl _prop + } + { gender } + } + \seq_if_empty:NTF \l_@@_dict_gender_seq + { + \tl_if_empty:NF \l_@@_ref_gender_tl + { + \msg_warning:nnxxx { zref-clever } + { language-no-gender } + { \l_@@_ref_language_tl } + { g } + { \l_@@_ref_gender_tl } + \tl_clear:N \l_@@_ref_gender_tl + } + } + { + \tl_if_empty:NF \l_@@_ref_gender_tl + { + \seq_if_in:NVF \l_@@_dict_gender_seq + \l_@@_ref_gender_tl + { + \msg_warning:nnxx { zref-clever } + { gender-not-declared } + { \l_@@_ref_language_tl } + { \l_@@_ref_gender_tl } + \tl_clear:N \l_@@_ref_gender_tl + } + } + } +% \end{macrocode} +% Ensure \cs{l_@@_capitalize_bool} is set to \texttt{true} when the language +% was declared with \opt{allcaps} option. +% \begin{macrocode} + \str_if_eq:eeT + { + \prop_item:cn + { + g_@@_dict_ + \l_@@_dict_language_tl _prop + } + { allcaps } + } + { true } + { \bool_set_true:N \l_@@_capitalize_bool } + } + { +% \end{macrocode} +% If the language itself is not declared, we still have to issue declension +% and gender warnings, if \opt{d} or \opt{g} options were used. +% \begin{macrocode} + \tl_if_empty:NF \l_@@_ref_decl_case_tl + { + \msg_warning:nnxx { zref-clever } { unknown-language-decl } + { \l_@@_ref_decl_case_tl } + { \l_@@_ref_language_tl } + \tl_clear:N \l_@@_ref_decl_case_tl + } + \tl_if_empty:NF \l_@@_ref_gender_tl + { + \msg_warning:nnxxx { zref-clever } + { language-no-gender } + { \l_@@_ref_language_tl } + { g } + { \l_@@_ref_gender_tl } + \tl_clear:N \l_@@_ref_gender_tl + } + } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{Dictionaries} +% +% Contrary to general options and type options, which are always \emph{local}, +% ``dictionaries'', ``translations'' or ``language-specific settings'' are +% always \emph{global}. Hence, the loading of built-in dictionaries, as well +% as settings done with \cs{zcLanguageSetup}, should set the relevant +% variables globally. +% +% The built-in dictionaries and their related infrastructure are designed to +% perform ``on the fly'' loading of dictionaries, ``lazily'' as needed. Much +% like \pkg{babel} does for languages not declared in the preamble, but used +% in the document. This offers some convenience, of course, and that's one +% reason to do it. But it also has the purpose of parsimony, of ``loading the +% least possible''. Therefore, we load at \texttt{begindocument} one single +% language (see \zcref[ref=title, noname]{sec:lang-option}), as specified by +% the user in the preamble with the \opt{lang} option or, failing any +% specification, the current language of the document, which is the default. +% Anything else is lazily loaded, on the fly, along the document. +% +% This design decision has also implications to the \emph{form} the dictionary +% files assumed. As far as my somewhat impressionistic sampling goes, +% dictionary or localization files of the most common packages in this area of +% functionality, are usually a set of commands which perform the relevant +% definitions and assignments in the preamble or at \texttt{begindocument}. +% This includes \pkg{translator}, \pkg{translations}, but also \pkg{babel}'s +% \file{.ldf} files, and \pkg{biblatex}'s \file{.lbx} files. I'm not really +% well acquainted with this machinery, but as far as I grasp, they all rely on +% some variation of \cs{ProvidesFile} and \cs{input}. And they can be safely +% \cs{input} without generating spurious content, because they rely on being +% loaded before the document has actually started. As far as I can tell, +% \pkg{babel}'s ``on the fly'' functionality is not based on the \file{.ldf} +% files, but on the \file{.ini} files, and on \cs{babelprovide}. And the +% \file{.ini} files are not in this form, but actually resemble +% ``configuration files'' of sorts, which means they are read and processed +% somehow else than with just \cs{input}. So we do the more or less the same +% here. It seems a reasonable way to ensure we can load dictionaries on the +% fly robustly mid-document, without getting paranoid with the last bit of +% white-space in them, and without introducing any undue content on the stream +% when we cannot afford to do it. Hence, \pkg{zref-clever}'s built-in +% dictionary files are a set of \emph{key-value options} which are read from +% the file, and fed to \texttt{\cs{keys_set:nn}\{zref-clever/dictionary\}} by +% \cs{@@_provide_dictionary:n}. And they use the same syntax and options as +% \cs{zcLanguageSetup} does. The dictionary file itself is read with +% \cs{ExplSyntaxOn} with the usual implications for white-space and catcodes. +% +% \cs{@@_provide_dictionary:n} is only meant to load the built-in +% dictionaries. For languages declared by the user, or for any settings to a +% known language made with \cs{zcLanguageSetup}, values are populated directly +% to a variable \cs{g_@@_dict_\meta{language}_prop}. Hence, there is no need +% to ``load'' anything in this case: definitions and assignments made by the +% user are performed immediately. +% +% +% \subsubsection*{Provide} +% +% \begin{macro}{\g_@@_loaded_dictionaries_seq} +% Used to keep track of whether a dictionary has already been loaded or not. +% \begin{macrocode} +\seq_new:N \g_@@_loaded_dictionaries_seq +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_@@_load_dict_verbose_bool} +% Controls whether \cs{@@_provide_dictionary:n} fails silently or verbosely +% in case of unknown languages or dictionaries not found. +% \begin{macrocode} +\bool_new:N \l_@@_load_dict_verbose_bool +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_provide_dictionary:n} +% Load dictionary for known \meta{language} if it is available and if it has +% not already been loaded. +% \begin{syntax} +% \cs{@@_provide_dictionary:n} \Arg{language} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_provide_dictionary:n #1 + { + \group_begin: + \@bsphack + \prop_get:NnNTF \g_@@_languages_prop {#1} + \l_@@_dict_language_tl + { + \seq_if_in:NVF + \g_@@_loaded_dictionaries_seq + \l_@@_dict_language_tl + { + \exp_args:Nx \file_get:nnNTF + { zref-clever- \l_@@_dict_language_tl .dict } + { \ExplSyntaxOn } + \l_tmpa_tl + { + \tl_clear:N \l_@@_setup_type_tl + \exp_args:NNx \seq_set_from_clist:Nn + \l_@@_dict_declension_seq + { + \prop_item:cn + { + g_@@_dict_ + \l_@@_dict_language_tl _prop + } + { declension } + } + \seq_if_empty:NTF \l_@@_dict_declension_seq + { \tl_clear:N \l_@@_dict_decl_case_tl } + { + \seq_get_left:NN \l_@@_dict_declension_seq + \l_@@_dict_decl_case_tl + } + \exp_args:NNx \seq_set_from_clist:Nn + \l_@@_dict_gender_seq + { + \prop_item:cn + { + g_@@_dict_ + \l_@@_dict_language_tl _prop + } + { gender } + } + \keys_set:nV { zref-clever / dictionary } \l_tmpa_tl + \seq_gput_right:NV \g_@@_loaded_dictionaries_seq + \l_@@_dict_language_tl + \msg_note:nnx { zref-clever } { dict-loaded } + { \l_@@_dict_language_tl } + } + { + \bool_if:NT \l_@@_load_dict_verbose_bool + { + \msg_warning:nnx { zref-clever } { dict-not-available } + { \l_@@_dict_language_tl } + } +% \end{macrocode} +% Even if we don't have the actual dictionary, we register it as ``loaded''. +% At this point, it is a known language, properly declared. There is no point +% in trying to load it multiple times, because users cannot really provide the +% dictionary files (well, technically they could, but we are working so they +% don't need to, and have better ways to do what they want). And if the users +% had provided some translations themselves, by means of \cs{zcLanguageSetup}, +% everything would be in place, and they could use the \opt{lang} option +% multiple times, and the \texttt{dict-not-available} warning would never go +% away. +% \begin{macrocode} + \seq_gput_right:NV \g_@@_loaded_dictionaries_seq + \l_@@_dict_language_tl + } + } + } + { + \bool_if:NT \l_@@_load_dict_verbose_bool + { \msg_warning:nnn { zref-clever } { unknown-language-load } {#1} } + } + \@esphack + \group_end: + } +\cs_generate_variant:Nn \@@_provide_dictionary:n { x } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_provide_dictionary_verbose:n} +% Does the same as \cs{@@_provide_dictionary:n}, but warns if the loading of +% the dictionary has failed. +% \begin{syntax} +% \cs{@@_provide_dictionary_verbose:n} \Arg{language} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_provide_dictionary_verbose:n #1 + { + \group_begin: + \bool_set_true:N \l_@@_load_dict_verbose_bool + \@@_provide_dictionary:n {#1} + \group_end: + } +\cs_generate_variant:Nn \@@_provide_dictionary_verbose:n { x } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro} +% { +% \@@_provide_dict_type_transl:nn , +% \@@_provide_dict_default_transl:nn , +% } +% A couple of auxiliary functions for the of +% \texttt{{zref-clever/dictionary}} keys set in +% \cs{@@_provide_dictionary:n}. They respectively ``provide'' (i.e. set if +% it value does not exist, do nothing if it already does) ``type-specific'' +% and ``default'' translations. Both receive \meta{key} and +% \meta{translation} as arguments, but \cs{@@_provide_dict_type_transl:nn} +% relies on the current value of \cs{l_@@_setup_type_tl}, as set by the +% \texttt{type} key. +% \begin{syntax} +% \cs{@@_provide_dict_type_transl:nn} \Arg{key} \Arg{translation} +% \cs{@@_provide_dict_default_transl:nn} \Arg{key} \Arg{translation} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_provide_dict_type_transl:nn #1#2 + { + \exp_args:Nnx \prop_gput_if_new:cnn + { g_@@_dict_ \l_@@_dict_language_tl _prop } + { type- \l_@@_setup_type_tl - #1 } {#2} + } +\cs_new_protected:Npn \@@_provide_dict_default_transl:nn #1#2 + { + \prop_gput_if_new:cnn + { g_@@_dict_ \l_@@_dict_language_tl _prop } + { default- #1 } {#2} + } +% \end{macrocode} +% \end{macro} +% +% +% The set of keys for \texttt{{zref-clever/dictionary}}, which is used to +% process the dictionary files in \cs{@@_provide_dictionary:n}. The no-op +% cases for each category have their messages sent to ``info''. These +% messages should not occur, as long as the dictionaries are well formed, but +% they're placed there nevertheless, and can be leveraged in regression tests. +% +% \begin{macrocode} +\keys_define:nn { zref-clever / dictionary } + { + type .code:n = + { + \tl_if_empty:nTF {#1} + { \tl_clear:N \l_@@_setup_type_tl } + { \tl_set:Nn \l_@@_setup_type_tl {#1} } + } , + case .code:n = + { + \seq_if_empty:NTF \l_@@_dict_declension_seq + { + \msg_info:nnxx { zref-clever } { language-no-decl-setup } + { \l_@@_dict_language_tl } {#1} + } + { + \seq_if_in:NnTF \l_@@_dict_declension_seq {#1} + { \tl_set:Nn \l_@@_dict_decl_case_tl {#1} } + { + \msg_info:nnxx { zref-clever } { unknown-decl-case } + {#1} { \l_@@_dict_language_tl } + \seq_get_left:NN \l_@@_dict_declension_seq + \l_@@_dict_decl_case_tl + } + } + } , + case .value_required:n = true , + gender .code:n = + { + \seq_if_empty:NTF \l_@@_dict_gender_seq + { + \msg_info:nnxxx { zref-clever } { language-no-gender } + { \l_@@_dict_language_tl } { gender } {#1} + } + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \msg_info:nnn { zref-clever } + { option-only-type-specific } { gender } + } + { + \seq_if_in:NnTF \l_@@_dict_gender_seq {#1} + { \@@_provide_dict_type_transl:nn { gender } {#1} } + { + \msg_info:nnxx { zref-clever } { gender-not-declared } + { \l_@@_dict_language_tl } {#1} + } + } + } + } , + gender .value_required:n = true , + } +\seq_map_inline:Nn + \c_@@_ref_options_necessarily_not_type_specific_seq + { + \keys_define:nn { zref-clever / dictionary } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { \@@_provide_dict_default_transl:nn {#1} {##1} } + { + \msg_info:nnn { zref-clever } + { option-not-type-specific } {#1} + } + } , + } + } +\seq_map_inline:Nn + \c_@@_ref_options_possibly_type_specific_seq + { + \keys_define:nn { zref-clever / dictionary } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { \@@_provide_dict_default_transl:nn {#1} {##1} } + { \@@_provide_dict_type_transl:nn {#1} {##1} } + } , + } + } +\seq_map_inline:Nn + \c_@@_ref_options_type_names_seq + { + \keys_define:nn { zref-clever / dictionary } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \msg_info:nnn { zref-clever } + { option-only-type-specific } {#1} + } + { + \tl_if_empty:NTF \l_@@_dict_decl_case_tl + { \@@_provide_dict_type_transl:nn {#1} {##1} } + { + \@@_provide_dict_type_transl:nn + { \l_@@_dict_decl_case_tl - #1 } {##1} + } + } + } , + } + } +% \end{macrocode} +% +% +% +% \subsubsection*{Fallback} +% +% All ``strings'' queried with \cs{@@_get_ref_string:nN} -- in practice, those +% in either \cs{c_@@_ref_options_necessarily_not_type_specific_seq} or +% \cs{c_@@_ref_options_possibly_type_specific_seq} -- must have their values +% set for ``fallback'', even if to empty ones, since this is what will be +% retrieved in the absence of a proper translation, which will be the case if +% \pkg{babel} or \pkg{polyglossia} is loaded and sets a language which +% \pkg{zref-clever} does not know. On the other hand, ``type names'' are not +% looked for in ``fallback'', since it is indeed impossible to provide any +% reasonable value for them for a ``specified but unknown language''. Also +% ``font'' options -- those in \cs{c_@@_ref_options_font_seq}, and queried +% with \cs{@@_get_ref_font:nN} -- do not need to be provided here, since the +% later function sets an empty value if the option is not found. +% +% \begin{macrocode} +\prop_new:N \g_@@_fallback_dict_prop +\prop_gset_from_keyval:Nn \g_@@_fallback_dict_prop + { + tpairsep = {,~} , + tlistsep = {,~} , + tlastsep = {,~} , + notesep = {~} , + namesep = {\nobreakspace} , + pairsep = {,~} , + listsep = {,~} , + lastsep = {,~} , + rangesep = {\textendash} , + refpre = {} , + refpos = {} , + } +% \end{macrocode} +% +% +% +% \subsubsection*{Get translations} +% +% \begin{macro}{\@@_get_type_transl:nnnNF} +% Get type-specific translation of \meta{key} for \meta{type} and +% \meta{language}, and store it in \meta{tl variable} if found. If not +% found, leave the \meta{false code} on the stream, in which case the value +% of \meta{tl variable} should not be relied upon. +% \begin{syntax} +% \cs{@@_get_type_transl:nnnNF} \Arg{language} \Arg{type} \Arg{key} +% ~~\meta{tl variable} \Arg{false code} +% \end{syntax} +% \begin{macrocode} +\prg_new_protected_conditional:Npnn + \@@_get_type_transl:nnnN #1#2#3#4 { F } + { + \prop_get:NnNTF \g_@@_languages_prop {#1} + \l_@@_dict_language_tl + { + \prop_get:cnNTF + { g_@@_dict_ \l_@@_dict_language_tl _prop } + { type- #2 - #3 } #4 + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn + \@@_get_type_transl:nnnN { xxxN , xxnN } { F } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_get_default_transl:nnNF} +% Get default translation of \meta{key} for \meta{language}, and store it in +% \meta{tl variable} if found. If not found, leave the \meta{false code} on +% the stream, in which case the value of \meta{tl variable} should not be +% relied upon. +% \begin{syntax} +% \cs{@@_get_default_transl:nnNF} \Arg{language} \Arg{key} +% ~~\meta{tl variable} \Arg{false code} +% \end{syntax} +% \begin{macrocode} +\prg_new_protected_conditional:Npnn + \@@_get_default_transl:nnN #1#2#3 { F } + { + \prop_get:NnNTF \g_@@_languages_prop {#1} + \l_@@_dict_language_tl + { + \prop_get:cnNTF + { g_@@_dict_ \l_@@_dict_language_tl _prop } + { default- #2 } #3 + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn + \@@_get_default_transl:nnN { xnN } { F } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_get_fallback_transl:nNF} +% Get fallback translation of \meta{key}, and store it in \meta{tl variable} +% if found. If not found, leave the \meta{false code} on the stream, in +% which case the value of \meta{tl variable} should not be relied upon. +% \begin{syntax} +% \cs{@@_get_fallback_transl:nNF} \Arg{key} +% ~~\meta{tl variable} \Arg{false code} +% \end{syntax} +% \begin{macrocode} +% {} +\prg_new_protected_conditional:Npnn + \@@_get_fallback_transl:nN #1#2 { F } + { + \prop_get:NnNTF \g_@@_fallback_dict_prop + { #1 } #2 + { \prg_return_true: } + { \prg_return_false: } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{Options} +% +% +% \subsubsection*{Auxiliary} +% +% +% \begin{macro}{\@@_prop_put_non_empty:Nnn} +% If \meta{value} is empty, remove \meta{key} from \meta{property list}. +% Otherwise, add \meta{key} = \meta{value} to \meta{property list}. +% \begin{syntax} +% \cs{@@_prop_put_non_empty:Nnn} \meta{property list} \Arg{key} \Arg{value} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_prop_put_non_empty:Nnn #1#2#3 + { + \tl_if_empty:nTF {#3} + { \prop_remove:Nn #1 {#2} } + { \prop_put:Nnn #1 {#2} {#3} } + } +% \end{macrocode} +% \end{macro} +% +% +% \subsubsection*{\opt{ref} option} +% +% \cs{l_@@_ref_property_tl} stores the property to which the reference is +% being made. Note that one thing \emph{must} be handled at this point: the +% existence of the property itself, as far as \pkg{zref} is concerned. This +% because typesetting relies on the check \cs{zref@ifrefcontainsprop}, which +% \emph{presumes} the property is defined and silently expands the \emph{true} +% branch if it is not (see \url{https://github.com/ho-tex/zref/issues/13}, +% thanks Ulrike Fischer). Therefore, before adding anything to +% \cs{l_@@_ref_property_tl}, check if first here with +% \cs{zref@ifpropundefined}: close it at the door. +% +% +% \begin{macrocode} +\tl_new:N \l_@@_ref_property_tl +\keys_define:nn { zref-clever / reference } + { + ref .code:n = + { + \zref@ifpropundefined {#1} + { + \msg_warning:nnn { zref-clever } { zref-property-undefined } {#1} + \tl_set:Nn \l_@@_ref_property_tl { default } + } + { \tl_set:Nn \l_@@_ref_property_tl {#1} } + } , + ref .initial:n = default , + ref .value_required:n = true , + page .meta:n = { ref = page }, + page .value_forbidden:n = true , + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{typeset} option} +% +% \begin{macrocode} +\bool_new:N \l_@@_typeset_ref_bool +\bool_new:N \l_@@_typeset_name_bool +\keys_define:nn { zref-clever / reference } + { + typeset .choice: , + typeset / both .code:n = + { + \bool_set_true:N \l_@@_typeset_ref_bool + \bool_set_true:N \l_@@_typeset_name_bool + } , + typeset / ref .code:n = + { + \bool_set_true:N \l_@@_typeset_ref_bool + \bool_set_false:N \l_@@_typeset_name_bool + } , + typeset / name .code:n = + { + \bool_set_false:N \l_@@_typeset_ref_bool + \bool_set_true:N \l_@@_typeset_name_bool + } , + typeset .initial:n = both , + typeset .value_required:n = true , + + noname .meta:n = { typeset = ref } , + noname .value_forbidden:n = true , + noref .meta:n = { typeset = name } , + noref .value_forbidden:n = true , + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{sort} option} +% +% \begin{macrocode} +\bool_new:N \l_@@_typeset_sort_bool +\keys_define:nn { zref-clever / reference } + { + sort .bool_set:N = \l_@@_typeset_sort_bool , + sort .initial:n = true , + sort .default:n = true , + nosort .meta:n = { sort = false }, + nosort .value_forbidden:n = true , + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{typesort} option} +% +% \cs{l_@@_typesort_seq} is stored reversed, since the sort priorities are +% computed in the negative range in \cs{@@_sort_default_different_types:nn}, +% so that we can implicitly rely on `0' being the ``last value'', and spare +% creating an integer variable using \cs{seq_map_indexed_inline:Nn}. +% +% \begin{macrocode} +\seq_new:N \l_@@_typesort_seq +\keys_define:nn { zref-clever / reference } + { + typesort .code:n = + { + \seq_set_from_clist:Nn \l_@@_typesort_seq {#1} + \seq_reverse:N \l_@@_typesort_seq + } , + typesort .initial:n = + { part , chapter , section , paragraph }, + typesort .value_required:n = true , + notypesort .code:n = + { \seq_clear:N \l_@@_typesort_seq } , + notypesort .value_forbidden:n = true , + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{comp} option} +% +% \begin{macrocode} +\bool_new:N \l_@@_typeset_compress_bool +\keys_define:nn { zref-clever / reference } + { + comp .bool_set:N = \l_@@_typeset_compress_bool , + comp .initial:n = true , + comp .default:n = true , + nocomp .meta:n = { comp = false }, + nocomp .value_forbidden:n = true , + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{range} option} +% +% \begin{macrocode} +\bool_new:N \l_@@_typeset_range_bool +\keys_define:nn { zref-clever / reference } + { + range .bool_set:N = \l_@@_typeset_range_bool , + range .initial:n = false , + range .default:n = true , + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{cap} and \opt{capfirst} options} +% +% \begin{macrocode} +\bool_new:N \l_@@_capitalize_bool +\bool_new:N \l_@@_capitalize_first_bool +\keys_define:nn { zref-clever / reference } + { + cap .bool_set:N = \l_@@_capitalize_bool , + cap .initial:n = false , + cap .default:n = true , + nocap .meta:n = { cap = false }, + nocap .value_forbidden:n = true , + + capfirst .bool_set:N = \l_@@_capitalize_first_bool , + capfirst .initial:n = false , + capfirst .default:n = true , + } +% \end{macrocode} +% +% +% \subsubsection*{\opt{abbrev} and \opt{noabbrevfirst} options} +% +% \begin{macrocode} +\bool_new:N \l_@@_abbrev_bool +\bool_new:N \l_@@_noabbrev_first_bool +\keys_define:nn { zref-clever / reference } + { + abbrev .bool_set:N = \l_@@_abbrev_bool , + abbrev .initial:n = false , + abbrev .default:n = true , + noabbrev .meta:n = { abbrev = false }, + noabbrev .value_forbidden:n = true , + + noabbrevfirst .bool_set:N = \l_@@_noabbrev_first_bool , + noabbrevfirst .initial:n = false , + noabbrevfirst .default:n = true , + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{S} option} +% +% \begin{macrocode} +\keys_define:nn { zref-clever / reference } + { + S .meta:n = + { capfirst = true , noabbrevfirst = true }, + S .value_forbidden:n = true , + } +% \end{macrocode} +% +% +% \subsubsection*{\opt{hyperref} option} +% +% \begin{macrocode} +\bool_new:N \l_@@_use_hyperref_bool +\bool_new:N \l_@@_warn_hyperref_bool +\keys_define:nn { zref-clever / reference } + { + hyperref .choice: , + hyperref / auto .code:n = + { + \bool_set_true:N \l_@@_use_hyperref_bool + \bool_set_false:N \l_@@_warn_hyperref_bool + } , + hyperref / true .code:n = + { + \bool_set_true:N \l_@@_use_hyperref_bool + \bool_set_true:N \l_@@_warn_hyperref_bool + } , + hyperref / false .code:n = + { + \bool_set_false:N \l_@@_use_hyperref_bool + \bool_set_false:N \l_@@_warn_hyperref_bool + } , + hyperref .initial:n = auto , + hyperref .default:n = auto + } +% \end{macrocode} +% +% \begin{macrocode} +\AddToHook { begindocument } + { + \@@_if_package_loaded:nTF { hyperref } + { + \bool_if:NT \l_@@_use_hyperref_bool + { \RequirePackage { zref-hyperref } } + } + { + \bool_if:NT \l_@@_warn_hyperref_bool + { \msg_warning:nn { zref-clever } { missing-hyperref } } + \bool_set_false:N \l_@@_use_hyperref_bool + } + \keys_define:nn { zref-clever / reference } + { + hyperref .code:n = + { \msg_warning:nn { zref-clever } { hyperref-preamble-only } } + } + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{nameinlink} option} +% +% \begin{macrocode} +\str_new:N \l_@@_nameinlink_str +\keys_define:nn { zref-clever / reference } + { + nameinlink .choice: , + nameinlink / true .code:n = + { \str_set:Nn \l_@@_nameinlink_str { true } } , + nameinlink / false .code:n = + { \str_set:Nn \l_@@_nameinlink_str { false } } , + nameinlink / single .code:n = + { \str_set:Nn \l_@@_nameinlink_str { single } } , + nameinlink / tsingle .code:n = + { \str_set:Nn \l_@@_nameinlink_str { tsingle } } , + nameinlink .initial:n = tsingle , + nameinlink .default:n = true , + } +% \end{macrocode} +% +% +% \subsubsection*{\opt{preposinlink} option} +% +% \begin{macrocode} +\bool_new:N \l_@@_preposinlink_bool +\keys_define:nn { zref-clever / reference } + { + preposinlink .bool_set:N = \l_@@_preposinlink_bool , + preposinlink .initial:n = false , + preposinlink .default:n = true , + } +% \end{macrocode} +% +% +% \subsubsection*{\opt{lang} option} +% \phantomsection{}\zlabel{sec:lang-option} +% +% \cs{l_@@_current_language_tl} is an internal alias for \pkg{babel}'s +% \cs{languagename} or \pkg{polyglossia}'s \cs{mainbabelname} and, if none of +% them is loaded, we set it to \texttt{english}. \cs{l_@@_main_language_tl} +% is an internal alias for \pkg{babel}'s \cs{bbl@main@language} or for +% \pkg{polyglossia}'s \cs{mainbabelname}, as the case may be. Note that for +% \pkg{polyglossia} we get \pkg{babel}'s language names, so that we only need +% to handle those internally. \cs{l_@@_ref_language_tl} is the internal +% variable which stores the language in which the reference is to be made. +% +% The overall setup here seems a little roundabout, but this is actually +% required. In the preamble, we (potentially) don't yet have values for the +% ``current'' and ``main'' document languages, this must be retrieved at a +% \texttt{begindocument} hook. The \texttt{begindocument} hook is responsible +% to get values for \cs{l_@@_current_language_tl} and +% \cs{l_@@_main_language_tl}, and to set the default for +% \cs{l_@@_ref_language_tl}. Package options, or preamble calls to +% \cs{zcsetup} are also hooked at \texttt{begindocument}, but come after the +% first hook, so that the pertinent variables have been set when they are +% executed. Finally, we set a third \texttt{begindocument} hook, at +% \texttt{begindocument/before}, so that it runs after any options set in the +% preamble. This hook redefines the \opt{lang} option for immediate execution +% in the document body, and ensures the \texttt{current} language's dictionary +% gets loaded, if it hadn't been already. +% +% For the \pkg{babel} and \pkg{polyglossia} variables which store the +% ``current'' and ``main'' languages, see +% \url{https://tex.stackexchange.com/a/233178}, including comments, +% particularly the one by Javier Bezos. For the \pkg{babel} and +% \pkg{polyglossia} variables which store the list of loaded languages, see +% \url{https://tex.stackexchange.com/a/281220}, including comments, +% particularly PLK's. Note, however, that languages loaded by +% \cs{babelprovide}, either directly, ``on the fly'', or with the +% \texttt{provide} option, \texttt{do not} get included in \cs{bbl@loaded}. +% + +% \begin{macrocode} +\tl_new:N \l_@@_ref_language_tl +\tl_new:N \l_@@_current_language_tl +\tl_new:N \l_@@_main_language_tl +\AddToHook { begindocument } + { + \@@_if_package_loaded:nTF { babel } + { + \tl_set:Nn \l_@@_current_language_tl { \languagename } + \tl_set:Nn \l_@@_main_language_tl { \bbl@main@language } + } + { + \@@_if_package_loaded:nTF { polyglossia } + { + \tl_set:Nn \l_@@_current_language_tl { \babelname } + \tl_set:Nn \l_@@_main_language_tl { \mainbabelname } + } + { + \tl_set:Nn \l_@@_current_language_tl { english } + \tl_set:Nn \l_@@_main_language_tl { english } + } + } +% \end{macrocode} +% Provide default value for \cs{l_@@_ref_language_tl} corresponding to option +% \opt{current}, but do so outside of the \pkg{l3keys} machinery (that is, +% instead of using \texttt{.initial:n}), so that we are able to distinguish +% when the user actually gave the option, in which case the dictionary loading +% is done verbosely, from when we are setting the default value (here), in +% which case the dictionary loading is done silently. +% \begin{macrocode} + \tl_set:Nn \l_@@_ref_language_tl + { \l_@@_current_language_tl } + } +% \end{macrocode} +% +% +% \begin{macrocode} +\keys_define:nn { zref-clever / reference } + { + lang .code:n = + { + \AddToHook { begindocument } + { + \str_case:nnF {#1} + { + { current } + { + \tl_set:Nn \l_@@_ref_language_tl + { \l_@@_current_language_tl } + \@@_provide_dictionary_verbose:x + { \l_@@_ref_language_tl } + } + + { main } + { + \tl_set:Nn \l_@@_ref_language_tl + { \l_@@_main_language_tl } + \@@_provide_dictionary_verbose:x + { \l_@@_ref_language_tl } + } + } + { + \prop_if_in:NnTF \g_@@_languages_prop {#1} + { \tl_set:Nn \l_@@_ref_language_tl {#1} } + { + \msg_warning:nnn { zref-clever } + { unknown-language-opt } {#1} + \tl_set:Nn \l_@@_ref_language_tl + { \l_@@_current_language_tl } + } + \@@_provide_dictionary_verbose:x + { \l_@@_ref_language_tl } + } + } + } , + lang .value_required:n = true , + } +% \end{macrocode} +% +% +% \begin{macrocode} +\AddToHook { begindocument / before } + { + \AddToHook { begindocument } + { +% \end{macrocode} +% If any \opt{lang} option has been given by the user, the corresponding +% language is already loaded, otherwise, ensure the default one +% (\texttt{current}) gets loaded early, but not verbosely. +% \begin{macrocode} + \@@_provide_dictionary:x { \l_@@_ref_language_tl } +% \end{macrocode} +% Redefinition of the \texttt{lang} key option for the document body. Also, +% drop the verbose dictionary loading in the document body, as it can become +% intrusive depending on the use case, and does not provide much ``juice'' +% anyway: in \cs{zcref} missing names warnings will already ensue. +% \begin{macrocode} + \keys_define:nn { zref-clever / reference } + { + lang .code:n = + { + \str_case:nnF {#1} + { + { current } + { + \tl_set:Nn \l_@@_ref_language_tl + { \l_@@_current_language_tl } + \@@_provide_dictionary:x + { \l_@@_ref_language_tl } + } + + { main } + { + \tl_set:Nn \l_@@_ref_language_tl + { \l_@@_main_language_tl } + \@@_provide_dictionary:x + { \l_@@_ref_language_tl } + } + } + { + \prop_if_in:NnTF \g_@@_languages_prop {#1} + { \tl_set:Nn \l_@@_ref_language_tl {#1} } + { + \msg_warning:nnn { zref-clever } + { unknown-language-opt } {#1} + \tl_set:Nn \l_@@_ref_language_tl + { \l_@@_current_language_tl } + } + \@@_provide_dictionary:x + { \l_@@_ref_language_tl } + } + } , + lang .value_required:n = true , + } + } + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{d} option} +% +% For setting the declension case. Short for convenience and for not +% polluting the markup too much given that, for languages that need it, it may +% get to be used frequently. +% +% Thanks \texttt{@samcarter} and Alan Munn for useful comments about +% declension on the TeX.SX chat. Also, Florent Rougon's efforts in this area, +% with the \pkg{xcref} package (\url{https://github.com/frougon/xcref}), have +% been an insightful source to frame the problem in general terms. +% +% \begin{macrocode} +\tl_new:N \l_@@_ref_decl_case_tl +\keys_define:nn { zref-clever / reference } + { + d .code:n = + { \msg_warning:nnn { zref-clever } { option-document-only } { d } } , + } +\AddToHook { begindocument } + { + \keys_define:nn { zref-clever / reference } + { +% \end{macrocode} +% We just store the value at this point, which is validated by +% \cs{@@_process_language_options:} after \cs{keys_set:nn}. +% \begin{macrocode} + d .tl_set:N = \l_@@_ref_decl_case_tl , + d .value_required:n = true , + } + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{nudge} \& co.\ options} +% +% \begin{macrocode} +\bool_new:N \l_@@_nudge_enabled_bool +\bool_new:N \l_@@_nudge_multitype_bool +\bool_new:N \l_@@_nudge_comptosing_bool +\bool_new:N \l_@@_nudge_singular_bool +\bool_new:N \l_@@_nudge_gender_bool +\tl_new:N \l_@@_ref_gender_tl +\keys_define:nn { zref-clever / reference } + { + nudge .choice: , + nudge / true .code:n = + { \bool_set_true:N \l_@@_nudge_enabled_bool } , + nudge / false .code:n = + { \bool_set_false:N \l_@@_nudge_enabled_bool } , + nudge / ifdraft .code:n = + { + \ifdraft + { \bool_set_false:N \l_@@_nudge_enabled_bool } + { \bool_set_true:N \l_@@_nudge_enabled_bool } + } , + nudge / iffinal .code:n = + { + \ifoptionfinal + { \bool_set_true:N \l_@@_nudge_enabled_bool } + { \bool_set_false:N \l_@@_nudge_enabled_bool } + } , + nudge .initial:n = false , + nudge .default:n = true , + nonudge .meta:n = { nudge = false } , + nonudge .value_forbidden:n = true , + nudgeif .code:n = + { + \bool_set_false:N \l_@@_nudge_multitype_bool + \bool_set_false:N \l_@@_nudge_comptosing_bool + \bool_set_false:N \l_@@_nudge_gender_bool + \clist_map_inline:nn {#1} + { + \str_case:nnF {##1} + { + { multitype } + { \bool_set_true:N \l_@@_nudge_multitype_bool } + { comptosing } + { \bool_set_true:N \l_@@_nudge_comptosing_bool } + { gender } + { \bool_set_true:N \l_@@_nudge_gender_bool } + { all } + { + \bool_set_true:N \l_@@_nudge_multitype_bool + \bool_set_true:N \l_@@_nudge_comptosing_bool + \bool_set_true:N \l_@@_nudge_gender_bool + } + } + { + \msg_warning:nnn { zref-clever } + { nudgeif-unknown-value } {##1} + } + } + } , + nudgeif .value_required:n = true , + nudgeif .initial:n = all , + sg .bool_set:N = \l_@@_nudge_singular_bool , + sg .initial:n = false , + sg .default:n = true , + g .code:n = + { \msg_warning:nnn { zref-clever } { option-document-only } { g } } , + } +\AddToHook { begindocument } + { + \keys_define:nn { zref-clever / reference } + { +% \end{macrocode} +% We just store the value at this point, which is validated by +% \cs{@@_process_language_options:} after \cs{keys_set:nn}. +% \begin{macrocode} + g .tl_set:N = \l_@@_ref_gender_tl , + g .value_required:n = true , + } + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{font} option} +% +% \opt{font} \emph{can't be used as a package option}, since the options get +% expanded by \LaTeX{} before being passed to the package (see +% \url{https://tex.stackexchange.com/a/489570}). It can be set in \cs{zcref} +% and, for global settings, with \cs{zcsetup}. Note that, technically, the +% ``raw'' options are already available as \cs{@raw@opt@\meta{package}.sty} +% (see \url{https://tex.stackexchange.com/a/618439}, thanks David Carlisle). +% +% \begin{macrocode} +\tl_new:N \l_@@_ref_typeset_font_tl +\keys_define:nn { zref-clever / reference } + { font .tl_set:N = \l_@@_ref_typeset_font_tl } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{titleref} option} +% +% \begin{macrocode} +\keys_define:nn { zref-clever / reference } + { + titleref .code:n = { \RequirePackage { zref-titleref } } , + titleref .value_forbidden:n = true , + } +\AddToHook { begindocument } + { + \keys_define:nn { zref-clever / reference } + { + titleref .code:n = + { \msg_warning:nn { zref-clever } { titleref-preamble-only } } + } + } +% \end{macrocode} +% +% +% \subsubsection*{\opt{note} option} +% +% \begin{macrocode} +\tl_new:N \l_@@_zcref_note_tl +\keys_define:nn { zref-clever / reference } + { + note .tl_set:N = \l_@@_zcref_note_tl , + note .value_required:n = true , + } +% \end{macrocode} +% +% +% \subsubsection*{\opt{check} option} +% +% Integration with \pkg{zref-check}. +% +% \begin{macrocode} +\bool_new:N \l_@@_zrefcheck_available_bool +\bool_new:N \l_@@_zcref_with_check_bool +\keys_define:nn { zref-clever / reference } + { + check .code:n = { \RequirePackage { zref-check } } , + check .value_forbidden:n = true , + } +\AddToHook { begindocument } + { + \@@_if_package_loaded:nTF { zref-check } + { + \bool_set_true:N \l_@@_zrefcheck_available_bool + \keys_define:nn { zref-clever / reference } + { + check .code:n = + { + \bool_set_true:N \l_@@_zcref_with_check_bool + \keys_set:nn { zref-check / zcheck } {#1} + } , + check .value_required:n = true , + } + } + { + \bool_set_false:N \l_@@_zrefcheck_available_bool + \keys_define:nn { zref-clever / reference } + { + check .value_forbidden:n = false , + check .code:n = + { \msg_warning:nn { zref-clever } { missing-zref-check } } , + } + } + } +% \end{macrocode} +% +% +% \subsubsection*{\opt{countertype} option} +% +% \cs{l_@@_counter_type_prop} is used by \texttt{zc@type} property, and stores +% a mapping from ``counter'' to ``reference type''. Only those counters whose +% type name is different from that of the counter need to be specified, since +% \texttt{zc@type} presumes the counter as the type if the counter is not +% found in \cs{l_@@_counter_type_prop}. +% +% \begin{macrocode} +\prop_new:N \l_@@_counter_type_prop +\keys_define:nn { zref-clever / label } + { + countertype .code:n = + { + \keyval_parse:nnn + { + \msg_warning:nnnn { zref-clever } + { key-requires-value } { countertype } + } + { + \@@_prop_put_non_empty:Nnn + \l_@@_counter_type_prop + } + {#1} + } , + countertype .value_required:n = true , + countertype .initial:n = + { + subsection = section , + subsubsection = section , + subparagraph = paragraph , + enumi = item , + enumii = item , + enumiii = item , + enumiv = item , + mpfootnote = footnote , + } , + } +% \end{macrocode} +% +% +% \subsubsection*{\opt{counterresetters} option} +% +% \cs{l_@@_counter_resetters_seq} is used by \cs{@@_counter_reset_by:n} to +% populate the \texttt{zc@enclval} property, and stores the list of counters +% which are potential ``enclosing counters'' for other counters. This option +% is constructed such that users can only \emph{add} items to the variable. +% There would be little gain and some risk in allowing removal, and the syntax +% of the option would become unnecessarily more complicated. Besides, users +% can already override, for any particular counter, the search done from the +% set in \cs{l_@@_counter_resetters_seq} with the \opt{counterresetby} option. +% +% \begin{macrocode} +\seq_new:N \l_@@_counter_resetters_seq +\keys_define:nn { zref-clever / label } + { + counterresetters .code:n = + { + \clist_map_inline:nn {#1} + { + \seq_if_in:NnF \l_@@_counter_resetters_seq {##1} + { + \seq_put_right:Nn + \l_@@_counter_resetters_seq {##1} + } + } + } , + counterresetters .initial:n = + { + part , + chapter , + section , + subsection , + subsubsection , + paragraph , + subparagraph , + }, + counterresetters .value_required:n = true , + } +% \end{macrocode} +% +% +% +% \subsubsection*{\opt{counterresetby} option} +% +% \cs{l_@@_counter_resetby_prop} is used by \cs{@@_counter_reset_by:n} to +% populate the \texttt{zc@enclval} property, and stores a mapping from +% counters to the counter which resets each of them. This mapping has +% precedence in \cs{@@_counter_reset_by:n} over the search through +% \cs{l_@@_counter_resetters_seq}. +% +% \begin{macrocode} +\prop_new:N \l_@@_counter_resetby_prop +\keys_define:nn { zref-clever / label } + { + counterresetby .code:n = + { + \keyval_parse:nnn + { + \msg_warning:nnn { zref-clever } + { key-requires-value } { counterresetby } + } + { + \@@_prop_put_non_empty:Nnn + \l_@@_counter_resetby_prop + } + {#1} + } , + counterresetby .value_required:n = true , + counterresetby .initial:n = + { +% \end{macrocode} +% The counters for the \texttt{enumerate} environment do not use the regular +% counter machinery for resetting on each level, but are nested nevertheless +% by other means, treat them as exception. +% \begin{macrocode} + enumii = enumi , + enumiii = enumii , + enumiv = enumiii , + } , + } +% \end{macrocode} +% +% +% \subsubsection*{\opt{currentcounter} option} +% +% \cs{l_@@_current_counter_tl} is pretty much the starting point of all of the +% data specification for label setting done by \pkg{zref} with our setup for +% it. It exists because we must provide some ``handle'' to specify the +% current counter for packages/features that do not set \cs{@currentcounter} +% appropriately. +% +% \begin{macrocode} +\tl_new:N \l_@@_current_counter_tl +\keys_define:nn { zref-clever / label } + { + currentcounter .tl_set:N = \l_@@_current_counter_tl , + currentcounter .value_required:n = true , + currentcounter .initial:n = \@currentcounter , + } +% \end{macrocode} +% +% +% \subsubsection*{\opt{nocompat} option} +% +% +% \begin{macrocode} +\bool_new:N \g_@@_nocompat_bool +\seq_new:N \g_@@_nocompat_modules_seq +\keys_define:nn { zref-clever / reference } + { + nocompat .code:n = + { + \tl_if_empty:nTF {#1} + { \bool_gset_true:N \g_@@_nocompat_bool } + { + \clist_map_inline:nn {#1} + { + \seq_if_in:NnF \g_@@_nocompat_modules_seq {##1} + { + \seq_gput_right:Nn + \g_@@_nocompat_modules_seq {##1} + } + } + } + } , + } +\AddToHook { begindocument } + { + \keys_define:nn { zref-clever / reference } + { + nocompat .code:n = + { + \msg_warning:nnn { zref-clever } + { option-preamble-only } { nocompat } + } + } + } +\AtEndOfPackage + { + \AddToHook { begindocument } + { + \seq_map_inline:Nn \g_@@_nocompat_modules_seq + { \msg_warning:nnn { zref-clever } { unknown-compat-module } {#1} } + } + } +% \end{macrocode} +% +% \begin{macro}{\@@_compat_module:nn} +% Function to be used for compatibility modules loading. It should load the +% module as long as \cs{l_@@_nocompat_bool} is false and \meta{module} is +% not in \cs{l_@@_nocompat_modules_seq}. The \texttt{begindocument} hook is +% needed so that we can have the option functional along the whole preamble, +% not just at package load time. This requirement might be relaxed if we +% made the option only available at load time, but this would not buy us +% much leeway anyway, since for most compatibility modules, we must test for +% the presence of packages at \texttt{begindocument}, only kernel features +% and document classes could be checked reliably before that. Besides, +% since we are using the new hook management system, there is always its +% functionality to deal with potential loading order issues. +% \begin{syntax} +% \cs{@@_compat_module:nn} \Arg{module} \Arg{code} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_compat_module:nn #1#2 + { + \AddToHook { begindocument } + { + \bool_if:NF \g_@@_nocompat_bool + { \seq_if_in:NnF \g_@@_nocompat_modules_seq {#1} {#2} } + \seq_gremove_all:Nn \g_@@_nocompat_modules_seq {#1} + } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \subsubsection*{Reference options} +% \zlabel{sec:reference-options} +% +% This is a set of options related to reference typesetting which receive +% equal treatment and, hence, are handled in batch. Since we are dealing with +% options to be passed to \cs{zcref} or to \cs{zcsetup} or at load time, only +% ``not necessarily type-specific'' options are pertinent here. However, they +% \emph{may} either be type-specific or language-specific, and thus must be +% stored in a property list, \cs{l_@@_ref_options_prop}, in order to be +% retrieved from the option \emph{name} by \cs{@@_get_ref_string:nN} and +% \cs{@@_get_ref_font:nN} according to context and precedence rules. +% +% The keys are set so that any value, including an empty one, is added to +% \cs{l_@@_ref_options_prop}, while a key with \emph{no value} removes the +% property from the list, so that these options can then fall back to lower +% precedence levels settings. For discussion about the used technique, see +% \zcref{sec:zcreftypesetup}. +% +% \begin{macrocode} +\prop_new:N \l_@@_ref_options_prop +\seq_map_inline:Nn + \c_@@_ref_options_reference_seq + { + \keys_define:nn { zref-clever / reference } + { + #1 .default:V = \c_novalue_tl , + #1 .code:n = + { + \tl_if_novalue:nTF {##1} + { \prop_remove:Nn \l_@@_ref_options_prop {#1} } + { \prop_put:Nnn \l_@@_ref_options_prop {#1} {##1} } + } , + } + } +% \end{macrocode} +% +% +% +% \subsubsection*{Package options} +% +% The options have been separated in two different groups, so that we can +% potentially apply them selectively to different contexts: \texttt{label} and +% \texttt{reference}. Currently, the only use of this selection is the +% ability to exclude label related options from \cs{zcref}'s options. Anyway, +% for load-time package options and for \cs{zcsetup} we want the whole set, so +% we aggregate the two into \texttt{zref-clever/zcsetup}, and use that here. +% +% \begin{macrocode} +\keys_define:nn { } + { + zref-clever / zcsetup .inherit:n = + { + zref-clever / label , + zref-clever / reference , + } + } +% \end{macrocode} +% +% +% Process load-time package options +% (\url{https://tex.stackexchange.com/a/15840}). +% \begin{macrocode} +\ProcessKeysOptions { zref-clever / zcsetup } +% \end{macrocode} +% +% +% +% \section{Configuration} +% +% \subsection{\cs{zcsetup}} +% +% +% \begin{macro}[int]{\zcsetup} +% Provide \cs{zcsetup}. +% \begin{syntax} +% \cs{zcsetup}\marg{options} +% \end{syntax} +% \begin{macrocode} +\NewDocumentCommand \zcsetup { m } + { \@@_zcsetup:n {#1} } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_zcsetup:n} +% A version of \cs{zcsetup} for internal use with variant. +% \begin{syntax} +% \cs{@@_zcsetup:n}\marg{options} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_zcsetup:n #1 + { \keys_set:nn { zref-clever / zcsetup } {#1} } +\cs_generate_variant:Nn \@@_zcsetup:n { x } +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{\cs{zcRefTypeSetup}} +% \zlabel{sec:zcreftypesetup} +% +% \cs{zcRefTypeSetup} is the main user interface for ``type-specific'' +% reference formatting. Settings done by this command have a higher +% precedence than any translation, hence they override any language-specific +% setting, either done at \cs{zcLanguageSetup} or by the package's +% dictionaries. On the other hand, they have a lower precedence than non +% type-specific general options. The \meta{options} should be given in the +% usual \texttt{key=val} format. The \meta{type} does not need to pre-exist, +% the property list variable to store the properties for the type gets created +% if need be. +% +% \begin{macro}[int]{\zcRefTypeSetup} +% \begin{syntax} +% \cs{zcRefTypeSetup} \marg{type} \marg{options} +% \end{syntax} +% \begin{macrocode} +\NewDocumentCommand \zcRefTypeSetup { m m } + { + \prop_if_exist:cF { l_@@_type_ #1 _options_prop } + { \prop_new:c { l_@@_type_ #1 _options_prop } } + \tl_set:Nn \l_@@_setup_type_tl {#1} + \keys_set:nn { zref-clever / typesetup } {#2} + } +% \end{macrocode} +% \end{macro} +% +% +% Inside \cs{zcRefTypeSetup} any of the options \emph{can} receive empty +% values, and those values, if they exist in the property list, will override +% translations, regardless of their emptiness. In principle, we could live +% with the situation of, once a setting has been made in +% \cs{l_@@_type__options_prop} or in \cs{l_@@_ref_options_prop} it stays +% there forever, and can only be overridden by a new value at the same +% precedence level or a higher one. But it would be nice if an user can +% ``unset'' an option at either of those scopes to go back to the lower +% precedence level of the translations at any given point. So both in +% \cs{zcRefTypeSetup} and in setting reference options (see +% \zcref{sec:reference-options}), we leverage the distinction of an ``empty +% valued key'' (\texttt{key=} or \texttt{key=\{\}}) from a ``key with no +% value'' (\texttt{key}). This distinction is captured internally by the +% lower-level key parsing, but must be made explicit at \cs{keys_set:nn} by +% means of the \texttt{.default:V} property of the key in \cs{keys_define:nn}. +% For the technique and some discussion about it, see +% \url{https://tex.stackexchange.com/q/614690} (thanks Jonathan P.\ Spratte, +% aka `Skillmon', and Phelype Oleinik) and +% \url{https://github.com/latex3/latex3/pull/988}. +% +% \begin{macrocode} +\seq_map_inline:Nn + \c_@@_ref_options_necessarily_not_type_specific_seq + { + \keys_define:nn { zref-clever / typesetup } + { + #1 .code:n = + { + \msg_warning:nnn { zref-clever } + { option-not-type-specific } {#1} + } , + } + } +% \end{macrocode} +% +% +% \begin{macrocode} +\seq_map_inline:Nn + \c_@@_ref_options_typesetup_seq + { + \keys_define:nn { zref-clever / typesetup } + { + #1 .default:V = \c_novalue_tl , + #1 .code:n = + { + \tl_if_novalue:nTF {##1} + { + \prop_remove:cn + { + l_@@_type_ + \l_@@_setup_type_tl _options_prop + } + {#1} + } + { + \prop_put:cnn + { + l_@@_type_ + \l_@@_setup_type_tl _options_prop + } + {#1} {##1} + } + } , + } + } +% \end{macrocode} +% +% +% +% \subsection{\cs{zcLanguageSetup}} +% +% \cs{zcLanguageSetup} is the main user interface for ``language-specific'' +% reference formatting, be it ``type-specific'' or not. The difference +% between the two cases is captured by the \texttt{type} key, which works as a +% sort of a ``switch''. Inside the \meta{options} argument of +% \cs{zcLanguageSetup}, any options made before the first \texttt{type} key +% declare ``default'' (non type-specific) translations. When the +% \texttt{type} key is given with a value, the options following it will set +% ``type-specific'' translations for that type. The current type can be +% switched off by an empty \texttt{type} key. \cs{zcLanguageSetup} is +% preamble only. +% +% \begin{macro}[int]{\zcLanguageSetup} +% \begin{syntax} +% \cs{zcLanguageSetup}\marg{language}\marg{options} +% \end{syntax} +% \begin{macrocode} +\NewDocumentCommand \zcLanguageSetup { m m } + { + \group_begin: + \prop_get:NnNTF \g_@@_languages_prop {#1} + \l_@@_dict_language_tl + { + \tl_clear:N \l_@@_setup_type_tl + \exp_args:NNx \seq_set_from_clist:Nn + \l_@@_dict_declension_seq + { + \prop_item:cn + { + g_@@_dict_ + \l_@@_dict_language_tl _prop + } + { declension } + } + \seq_if_empty:NTF \l_@@_dict_declension_seq + { \tl_clear:N \l_@@_dict_decl_case_tl } + { + \seq_get_left:NN \l_@@_dict_declension_seq + \l_@@_dict_decl_case_tl + } + \exp_args:NNx \seq_set_from_clist:Nn + \l_@@_dict_gender_seq + { + \prop_item:cn + { + g_@@_dict_ + \l_@@_dict_language_tl _prop + } + { gender } + } + \keys_set:nn { zref-clever / langsetup } {#2} + } + { \msg_warning:nnn { zref-clever } { unknown-language-setup } {#1} } + \group_end: + } +\@onlypreamble \zcLanguageSetup +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro} +% { +% \@@_declare_type_transl:nnnn , +% \@@_declare_default_transl:nnn , +% } +% A couple of auxiliary functions for the of +% \texttt{{zref-clever/translation}} keys set in \cs{zcLanguageSetup}. They +% respectively declare (unconditionally set) ``type-specific'' and +% ``default'' translations. +% \begin{syntax} +% \cs{@@_declare_type_transl:nnnn} \Arg{language} \Arg{type} +% ~~\Arg{key} \Arg{translation} +% \cs{@@_declare_default_transl:nnn} \Arg{language} +% ~~\Arg{key} \Arg{translation} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_declare_type_transl:nnnn #1#2#3#4 + { + \prop_gput:cnn { g_@@_dict_ #1 _prop } + { type- #2 - #3 } {#4} + } +\cs_generate_variant:Nn \@@_declare_type_transl:nnnn { VVnn , VVxn } +\cs_new_protected:Npn \@@_declare_default_transl:nnn #1#2#3 + { + \prop_gput:cnn { g_@@_dict_ #1 _prop } + { default- #2 } {#3} + } +\cs_generate_variant:Nn \@@_declare_default_transl:nnn { Vnn } +% \end{macrocode} +% \end{macro} +% +% +% The set of keys for \texttt{{zref-clever/langsetup}}, which is used to +% set language-specific translations in \cs{zcLanguageSetup}. +% +% \begin{macrocode} +\keys_define:nn { zref-clever / langsetup } + { + type .code:n = + { + \tl_if_empty:nTF {#1} + { \tl_clear:N \l_@@_setup_type_tl } + { \tl_set:Nn \l_@@_setup_type_tl {#1} } + } , + case .code:n = + { + \seq_if_empty:NTF \l_@@_dict_declension_seq + { + \msg_warning:nnxx { zref-clever } { language-no-decl-setup } + { \l_@@_dict_language_tl } {#1} + } + { + \seq_if_in:NnTF \l_@@_dict_declension_seq {#1} + { \tl_set:Nn \l_@@_dict_decl_case_tl {#1} } + { + \msg_warning:nnxx { zref-clever } { unknown-decl-case } + {#1} { \l_@@_dict_language_tl } + \seq_get_left:NN \l_@@_dict_declension_seq + \l_@@_dict_decl_case_tl + } + } + } , + case .value_required:n = true , + gender .code:n = + { + \seq_if_empty:NTF \l_@@_dict_gender_seq + { + \msg_warning:nnxxx { zref-clever } { language-no-gender } + { \l_@@_dict_language_tl } { gender } {#1} + } + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \msg_warning:nnn { zref-clever } + { option-only-type-specific } { gender } + } + { + \seq_if_in:NnTF \l_@@_dict_gender_seq {#1} + { + \@@_declare_type_transl:VVnn + \l_@@_dict_language_tl + \l_@@_setup_type_tl + { gender } {#1} + } + { + \msg_warning:nnxx { zref-clever } { gender-not-declared } + { \l_@@_dict_language_tl } {#1} + } + } + } + } , + gender .value_required:n = true , + } +\seq_map_inline:Nn + \c_@@_ref_options_necessarily_not_type_specific_seq + { + \keys_define:nn { zref-clever / langsetup } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \@@_declare_default_transl:Vnn + \l_@@_dict_language_tl + {#1} {##1} + } + { + \msg_warning:nnn { zref-clever } + { option-not-type-specific } {#1} + } + } , + } + } +\seq_map_inline:Nn + \c_@@_ref_options_possibly_type_specific_seq + { + \keys_define:nn { zref-clever / langsetup } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \@@_declare_default_transl:Vnn + \l_@@_dict_language_tl + {#1} {##1} + } + { + \@@_declare_type_transl:VVnn + \l_@@_dict_language_tl + \l_@@_setup_type_tl + {#1} {##1} + } + } , + } + } +\seq_map_inline:Nn + \c_@@_ref_options_type_names_seq + { + \keys_define:nn { zref-clever / langsetup } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l_@@_setup_type_tl + { + \msg_warning:nnn { zref-clever } + { option-only-type-specific } {#1} + } + { + \tl_if_empty:NTF \l_@@_dict_decl_case_tl + { + \@@_declare_type_transl:VVnn + \l_@@_dict_language_tl + \l_@@_setup_type_tl + {#1} {##1} + } + { + \@@_declare_type_transl:VVxn + \l_@@_dict_language_tl + \l_@@_setup_type_tl + { \l_@@_dict_decl_case_tl - #1 } {##1} + } + } + } , + } + } +% \end{macrocode} +% +% +% +% \section{User interface} +% +% \subsection{\cs{zcref}} +% +% +% \begin{macro}[int]{\zcref} +% The main user command of the package. +% \begin{syntax} +% \cs{zcref}\meta{*}\oarg{options}\marg{labels} +% \end{syntax} +% \begin{macrocode} +\NewDocumentCommand \zcref { s O { } m } + { \zref@wrapper@babel \@@_zcref:nnn {#3} {#1} {#2} } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_zcref:nnnn} +% An intermediate internal function, which does the actual heavy lifting, +% and places \Arg{labels} as first argument, so that it can be protected by +% \cs{zref@wrapper@babel} in \cs{zcref}. +% \begin{syntax} +% \cs{@@_zcref:nnnn} \Arg{labels} \Arg{*} \Arg{options} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_zcref:nnn #1#2#3 + { + \group_begin: +% \end{macrocode} +% Set options. +% \begin{macrocode} + \keys_set:nn { zref-clever / reference } {#3} +% \end{macrocode} +% Store arguments values. +% \begin{macrocode} + \seq_set_from_clist:Nn \l_@@_zcref_labels_seq {#1} + \bool_set:Nn \l_@@_link_star_bool {#2} +% \end{macrocode} +% Ensure dictionary for reference language is loaded, if available. We cannot +% rely on \cs{keys_set:nn} for the task, since if the \opt{lang} option is set +% for \texttt{current}, the actual language may have changed outside our +% control. \cs{@@_provide_dictionary:x} does nothing if the dictionary is +% already loaded. +% \begin{macrocode} + \@@_provide_dictionary:x { \l_@@_ref_language_tl } +% \end{macrocode} +% Process \cs{zcDeclareLanguage} options. +% \begin{macrocode} + \@@_process_language_options: +% \end{macrocode} +% Integration with \pkg{zref-check}. +% \begin{macrocode} + \bool_lazy_and:nnT + { \l_@@_zrefcheck_available_bool } + { \l_@@_zcref_with_check_bool } + { \zrefcheck_zcref_beg_label: } +% \end{macrocode} +% Sort the labels. +% \begin{macrocode} + \bool_lazy_or:nnT + { \l_@@_typeset_sort_bool } + { \l_@@_typeset_range_bool } + { \@@_sort_labels: } +% \end{macrocode} +% Typeset the references. Also, set the reference font, and group it, so that +% it does not leak to the note. +% \begin{macrocode} + \group_begin: + \l_@@_ref_typeset_font_tl + \@@_typeset_refs: + \group_end: +% \end{macrocode} +% Typeset \texttt{note}. +% \begin{macrocode} + \tl_if_empty:NF \l_@@_zcref_note_tl + { + \@@_get_ref_string:nN { notesep } \l_tmpa_tl + \l_tmpa_tl + \l_@@_zcref_note_tl + } +% \end{macrocode} +% Integration with \pkg{zref-check}. +% \begin{macrocode} + \bool_lazy_and:nnT + { \l_@@_zrefcheck_available_bool } + { \l_@@_zcref_with_check_bool } + { + \zrefcheck_zcref_end_label_maybe: + \zrefcheck_zcref_run_checks_on_labels:n + { \l_@@_zcref_labels_seq } + } +% \end{macrocode} +% Integration with \pkg{mathtools}. +% \begin{macrocode} + \bool_if:NT \l_@@_mathtools_showonlyrefs_bool + { + \@@_mathtools_showonlyrefs:n + { \l_@@_zcref_labels_seq } + } + \group_end: + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_@@_zcref_labels_seq, \l_@@_link_star_bool} +% \begin{macrocode} +\seq_new:N \l_@@_zcref_labels_seq +\bool_new:N \l_@@_link_star_bool +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection{\cs{zcpageref}} +% +% +% \begin{macro}[int]{\zcpageref} +% A \cs{pageref} equivalent of \cs{zcref}. +% \begin{syntax} +% \cs{zcpageref}\meta{*}\oarg{options}\marg{labels} +% \end{syntax} +% \begin{macrocode} +\NewDocumentCommand \zcpageref { s O { } m } + { + \IfBooleanTF {#1} + { \zcref*[#2, ref = page] {#3} } + { \zcref [#2, ref = page] {#3} } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \section{Sorting} +% +% Sorting is certainly a ``big task'' for \pkg{zref-clever} but, in the end, +% it boils down to ``carefully done branching'', and quite some of it. The +% sorting of ``page'' references is very much lightened by the availability of +% \texttt{abspage}, from the \pkg{zref-abspage} module, which offers ``just +% what we need'' for our purposes. The sorting of ``default'' references +% falls on two main cases: i) labels of the same type; ii) labels of different +% types. The first case is sorted according to the priorities set by the +% \opt{typesort} option or, if that is silent for the case, by the order in +% which labels were given by the user in \cs{zcref}. The second case is the +% most involved one, since it is possible for multiple counters to be bundled +% together in a single reference type. Because of this, sorting must take +% into account the whole chain of ``enclosing counters'' for the counters of +% the labels at hand. +% +% \begin{macro} +% { +% \l_@@_label_type_a_tl , +% \l_@@_label_type_b_tl , +% \l_@@_label_enclval_a_tl , +% \l_@@_label_enclval_b_tl , +% \l_@@_label_extdoc_a_tl , +% \l_@@_label_extdoc_b_tl , +% } +% Auxiliary variables, for use in sorting, and some also in typesetting. +% Used to store reference information -- label properties -- of the +% ``current'' (\texttt{a}) and ``next'' (\texttt{b}) labels. +% \begin{macrocode} +\tl_new:N \l_@@_label_type_a_tl +\tl_new:N \l_@@_label_type_b_tl +\tl_new:N \l_@@_label_enclval_a_tl +\tl_new:N \l_@@_label_enclval_b_tl +\tl_new:N \l_@@_label_extdoc_a_tl +\tl_new:N \l_@@_label_extdoc_b_tl +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_@@_sort_decided_bool} +% Auxiliary variable for \cs{@@_sort_default_same_type:nn}, signals if the +% sorting between two labels has been decided or not. +% \begin{macrocode} +\bool_new:N \l_@@_sort_decided_bool +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_@@_sort_prior_a_int,\l_@@_sort_prior_b_int} +% Auxiliary variables for \cs{@@_sort_default_different_types:nn}. Store +% the sort priority of the ``current'' and ``next'' labels. +% \begin{macrocode} +\int_new:N \l_@@_sort_prior_a_int +\int_new:N \l_@@_sort_prior_b_int +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\l_@@_label_types_seq} +% Stores the order in which reference types appear in the label list +% supplied by the user in \cs{zcref}. This variable is populated by +% \cs{@@_label_type_put_new_right:n} at the start of \cs{@@_sort_labels:}. +% This order is required as a ``last resort'' sort criterion between the +% reference types, for use in \cs{@@_sort_default_different_types:nn}. +% \begin{macrocode} +\seq_new:N \l_@@_label_types_seq +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_sort_labels:} +% The main sorting function. It does not receive arguments, but it is +% expected to be run inside \cs{@@_zcref:nnnn} where a number of environment +% variables are to be set appropriately. In particular, +% \cs{l_@@_zcref_labels_seq} should contain the labels received as argument +% to \cs{zcref}, and the function performs its task by sorting this +% variable. +% \begin{macrocode} +\cs_new_protected:Npn \@@_sort_labels: + { +% \end{macrocode} +% Store label types sequence. +% \begin{macrocode} + \seq_clear:N \l_@@_label_types_seq + \tl_if_eq:NnF \l_@@_ref_property_tl { page } + { + \seq_map_function:NN \l_@@_zcref_labels_seq + \@@_label_type_put_new_right:n + } +% \end{macrocode} +% Sort. +% \begin{macrocode} + \seq_sort:Nn \l_@@_zcref_labels_seq + { + \zref@ifrefundefined {##1} + { + \zref@ifrefundefined {##2} + { + % Neither label is defined. + \sort_return_same: + } + { + % The second label is defined, but the first isn't, leave the + % undefined first (to be more visible). + \sort_return_same: + } + } + { + \zref@ifrefundefined {##2} + { + % The first label is defined, but the second isn't, bring the + % second forward. + \sort_return_swapped: + } + { + % The interesting case: both labels are defined. References + % to the "default" property or to the "page" are quite + % different with regard to sorting, so we branch them here to + % specialized functions. + \tl_if_eq:NnTF \l_@@_ref_property_tl { page } + { \@@_sort_page:nn {##1} {##2} } + { \@@_sort_default:nn {##1} {##2} } + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_label_type_put_new_right:n} +% Auxiliary function used to store the order in which reference types appear +% in the label list supplied by the user in \cs{zcref}. It is expected to +% be run inside \cs{@@_sort_labels:}, and stores the types sequence in +% \cs{l_@@_label_types_seq}. I have tried to handle the same task inside +% \cs{seq_sort:Nn} in \cs{@@_sort_labels:} to spare mapping over +% \cs{l_@@_zcref_labels_seq}, but it turned out it not to be easy to rely on +% the order the labels get processed at that point, since the variable is +% being sorted there. Besides, the mapping is simple, not a particularly +% expensive operation. Anyway, this keeps things clean. +% \begin{syntax} +% \cs{@@_label_type_put_new_right:n} \Arg{label} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_label_type_put_new_right:n #1 + { + \@@_def_extract:Nnnn + \l_@@_label_type_a_tl {#1} { zc@type } { \c_empty_tl } + \seq_if_in:NVF \l_@@_label_types_seq + \l_@@_label_type_a_tl + { + \seq_put_right:NV \l_@@_label_types_seq + \l_@@_label_type_a_tl + } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_sort_default:nn} +% The heavy-lifting function for sorting of defined labels for ``default'' +% references (that is, a standard reference, not to ``page''). This +% function is expected to be called within the sorting loop of +% \cs{@@_sort_labels:} and receives the pair of labels being considered for +% a change of order or not. It should \emph{always} ``return'' either +% \cs{sort_return_same:} or \cs{sort_return_swapped:}. +% \begin{syntax} +% \cs{@@_sort_default:nn} \Arg{label a} \Arg{label b} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_sort_default:nn #1#2 + { + \@@_def_extract:Nnnn + \l_@@_label_type_a_tl {#1} { zc@type } { zc@missingtype } + \@@_def_extract:Nnnn + \l_@@_label_type_b_tl {#2} { zc@type } { zc@missingtype } + + \tl_if_eq:NNTF + \l_@@_label_type_a_tl + \l_@@_label_type_b_tl + { \@@_sort_default_same_type:nn {#1} {#2} } + { \@@_sort_default_different_types:nn {#1} {#2} } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_sort_default_same_type:nn} +% \begin{syntax} +% \cs{@@_sort_default_same_type:nn} \Arg{label a} \Arg{label b} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_sort_default_same_type:nn #1#2 + { + \@@_def_extract:Nnnn \l_@@_label_enclval_a_tl + {#1} { zc@enclval } { \c_empty_tl } + \tl_reverse:N \l_@@_label_enclval_a_tl + \@@_def_extract:Nnnn \l_@@_label_enclval_b_tl + {#2} { zc@enclval } { \c_empty_tl } + \tl_reverse:N \l_@@_label_enclval_b_tl + \@@_def_extract:Nnnn \l_@@_label_extdoc_a_tl + {#1} { externaldocument } { \c_empty_tl } + \@@_def_extract:Nnnn \l_@@_label_extdoc_b_tl + {#2} { externaldocument } { \c_empty_tl } + + \bool_set_false:N \l_@@_sort_decided_bool + + % First we check if there's any "external document" difference (coming + % from 'zref-xr') and, if so, sort based on that. + \tl_if_eq:NNF + \l_@@_label_extdoc_a_tl + \l_@@_label_extdoc_b_tl + { + \bool_if:nTF + { + \tl_if_empty_p:V \l_@@_label_extdoc_a_tl && + ! \tl_if_empty_p:V \l_@@_label_extdoc_b_tl + } + { + \bool_set_true:N \l_@@_sort_decided_bool + \sort_return_same: + } + { + \bool_if:nTF + { + ! \tl_if_empty_p:V \l_@@_label_extdoc_a_tl && + \tl_if_empty_p:V \l_@@_label_extdoc_b_tl + } + { + \bool_set_true:N \l_@@_sort_decided_bool + \sort_return_swapped: + } + { + \bool_set_true:N \l_@@_sort_decided_bool + % Two different "external documents": last resort, sort by the + % document name itself. + \str_compare:eNeTF + { \l_@@_label_extdoc_b_tl } < + { \l_@@_label_extdoc_a_tl } + { \sort_return_swapped: } + { \sort_return_same: } + } + } + } + + \bool_until_do:Nn \l_@@_sort_decided_bool + { + \bool_if:nTF + { + % Both are empty: neither label has any (further) "enclosing + % counters" (left). + \tl_if_empty_p:V \l_@@_label_enclval_a_tl && + \tl_if_empty_p:V \l_@@_label_enclval_b_tl + } + { + \bool_set_true:N \l_@@_sort_decided_bool + \int_compare:nNnTF + { \@@_extract:nnn {#1} { zc@cntval } { -1 } } + > + { \@@_extract:nnn {#2} { zc@cntval } { -1 } } + { \sort_return_swapped: } + { \sort_return_same: } + } + { + \bool_if:nTF + { + % `a' is empty (and `b' is not): `b' may be nested in `a'. + \tl_if_empty_p:V \l_@@_label_enclval_a_tl + } + { + \bool_set_true:N \l_@@_sort_decided_bool + \int_compare:nNnTF + { \@@_extract:nnn {#1} { zc@cntval } { } } + > + { \tl_head:N \l_@@_label_enclval_b_tl } + { \sort_return_swapped: } + { \sort_return_same: } + } + { + \bool_if:nTF + { + % `b' is empty (and `a' is not): `a' may be nested in `b'. + \tl_if_empty_p:V \l_@@_label_enclval_b_tl + } + { + \bool_set_true:N \l_@@_sort_decided_bool + \int_compare:nNnTF + { \tl_head:N \l_@@_label_enclval_a_tl } + < + { \@@_extract:nnn {#2} { zc@cntval } { } } + { \sort_return_same: } + { \sort_return_swapped: } + } + { + % Neither is empty: we can compare the values of the + % current enclosing counter in the loop, if they are + % equal, we are still in the loop, if they are not, a + % sorting decision can be made directly. + \int_compare:nNnTF + { \tl_head:N \l_@@_label_enclval_a_tl } + = + { \tl_head:N \l_@@_label_enclval_b_tl } + { + \tl_set:Nx \l_@@_label_enclval_a_tl + { \tl_tail:N \l_@@_label_enclval_a_tl } + \tl_set:Nx \l_@@_label_enclval_b_tl + { \tl_tail:N \l_@@_label_enclval_b_tl } + } + { + \bool_set_true:N \l_@@_sort_decided_bool + \int_compare:nNnTF + { \tl_head:N \l_@@_label_enclval_a_tl } + > + { \tl_head:N \l_@@_label_enclval_b_tl } + { \sort_return_swapped: } + { \sort_return_same: } + } + } + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_sort_default_different_types:nn} +% \begin{syntax} +% \cs{@@_sort_default_different_types:nn} \Arg{label a} \Arg{label b} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_sort_default_different_types:nn #1#2 + { +% \end{macrocode} +% Retrieve sort priorities for \meta{label a} and \meta{label b}. +% \cs{l_@@_typesort_seq} was stored in reverse sequence, and we compute the +% sort priorities in the negative range, so that we can implicitly rely on `0' +% being the ``last value''. +% \begin{macrocode} + \int_zero:N \l_@@_sort_prior_a_int + \int_zero:N \l_@@_sort_prior_b_int + \seq_map_indexed_inline:Nn \l_@@_typesort_seq + { + \tl_if_eq:nnTF {##2} {{othertypes}} + { + \int_compare:nNnT { \l_@@_sort_prior_a_int } = { 0 } + { \int_set:Nn \l_@@_sort_prior_a_int { - ##1 } } + \int_compare:nNnT { \l_@@_sort_prior_b_int } = { 0 } + { \int_set:Nn \l_@@_sort_prior_b_int { - ##1 } } + } + { + \tl_if_eq:NnTF \l_@@_label_type_a_tl {##2} + { \int_set:Nn \l_@@_sort_prior_a_int { - ##1 } } + { + \tl_if_eq:NnT \l_@@_label_type_b_tl {##2} + { \int_set:Nn \l_@@_sort_prior_b_int { - ##1 } } + } + } + } +% \end{macrocode} +% Then do the actual sorting. +% \begin{macrocode} + \bool_if:nTF + { + \int_compare_p:nNn + { \l_@@_sort_prior_a_int } < + { \l_@@_sort_prior_b_int } + } + { \sort_return_same: } + { + \bool_if:nTF + { + \int_compare_p:nNn + { \l_@@_sort_prior_a_int } > + { \l_@@_sort_prior_b_int } + } + { \sort_return_swapped: } + { + % Sort priorities are equal: the type that occurs first in + % `labels', as given by the user, is kept (or brought) forward. + \seq_map_inline:Nn \l_@@_label_types_seq + { + \tl_if_eq:NnTF \l_@@_label_type_a_tl {##1} + { \seq_map_break:n { \sort_return_same: } } + { + \tl_if_eq:NnT \l_@@_label_type_b_tl {##1} + { \seq_map_break:n { \sort_return_swapped: } } + } + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_sort_page:nn} +% The sorting function for sorting of defined labels for references to +% ``page''. This function is expected to be called within the sorting loop +% of \cs{@@_sort_labels:} and receives the pair of labels being considered +% for a change of order or not. It should \emph{always} ``return'' either +% \cs{sort_return_same:} or \cs{sort_return_swapped:}. Compared to the +% sorting of default labels, this is a piece of cake (thanks to +% \texttt{abspage}). +% \begin{syntax} +% \cs{@@_sort_page:nn} \Arg{label a} \Arg{label b} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_sort_page:nn #1#2 + { + \int_compare:nNnTF + { \@@_extract:nnn {#1} { abspage } { -1 } } + > + { \@@_extract:nnn {#2} { abspage } { -1 } } + { \sort_return_swapped: } + { \sort_return_same: } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \section{Typesetting} +% +% ``Typesetting'' the reference, which here includes the parsing of the labels +% and eventual compression of labels in sequence into ranges, is definitely +% the ``crux'' of \pkg{zref-clever}. This because we process the label set as +% a stack, in a single pass, and hence ``parsing'', ``compressing'', and +% ``typesetting'' must be decided upon at the same time, making it difficult +% to slice the job into more specific and self-contained tasks. So, do bear +% this in mind before you curse me for the length of some of the functions +% below, or before a more orthodox ``docstripper'' complains about me not +% sticking to code commenting conventions to keep the code more readable in +% the \file{.dtx} file. +% +% While processing the label stack (kept in \cs{l_@@_typeset_labels_seq}), +% \cs{@@_typeset_refs:} ``sees'' two labels, and two labels only, the +% ``current'' one (kept in \cs{l_@@_label_a_tl}), and the ``next'' one (kept +% in \cs{l_@@_label_b_tl}). However, the typesetting needs (a lot) more +% information than just these two immediate labels to make a number of +% critical decisions. Some examples: i) We cannot know if labels ``current'' +% and ``next'' of the same type are a ``pair'', or just ``elements in a +% list'', until we examine the label after ``next''; ii) If the ``next'' label +% is of the same type as the ``current'', and it is in immediate sequence to +% it, it potentially forms a ``range'', but we cannot know if ``next'' is +% actually the end of the range until we examined an arbitrary number of +% labels, and found one which is not in sequence from the previous one; iii) +% When processing a type block, the ``name'' comes first, however, we only +% know if that name should be plural, or if it should be included in the +% hyperlink, after processing an arbitrary number of labels and find one of a +% different type. One could naively assume that just examining ``next'' would +% be enough for this, since we can know if it is of the same type or not. +% Alas, ``there be ranges'', and a compression operation may boil down to a +% single element, so we have to process the whole type block to know how its +% name should be typeset; iv) Similar issues apply to lists of type blocks, +% each of which is of arbitrary length: we can only know if two type blocks +% form a ``pair'' or are ``elements in a list'' when we finish the +% block. Etc.\ etc.\ etc. +% +% We handle this by storing the reference ``pieces'' in ``queues'', instead of +% typesetting them immediately upon processing. The ``queues'' get typeset at +% the point where all the information needed is available, which usually +% happens when a type block finishes (we see something of a different type in +% ``next'', signaled by \cs{l_@@_last_of_type_bool}), or the stack itself +% finishes (has no more elements, signaled by \cs{l_@@_typeset_last_bool}). +% And, in processing a type block, the type ``name'' gets added last (on the +% left) of the queue. The very first reference of its type always follows the +% name, since it may form a hyperlink with it (so we keep it stored +% separately, in \cs{l_@@_type_first_label_tl}, with +% \cs{l_@@_type_first_label_type_tl} being its type). And, since we may need +% up to two type blocks in storage before typesetting, we have two of these +% ``queues'': \cs{l_@@_typeset_queue_curr_tl} and +% \cs{l_@@_typeset_queue_prev_tl}. +% +% Some of the relevant cases (e.g., distinguishing ``pair'' from ``list'') are +% handled by counters, the main ones are: one for the ``type'' +% (\cs{l_@@_type_count_int}) and one for the ``label in the current type +% block'' (\cs{l_@@_label_count_int}). +% +% Range compression, in particular, relies heavily on counting to be able do +% distinguish relevant cases. \cs{l_@@_range_count_int} counts the number of +% elements in the current sequential ``streak'', and +% \cs{l_@@_range_same_count_int} counts the number of \emph{equal} elements in +% that same ``streak''. The difference between the two allows us to +% distinguish the cases in which a range actually ``skips'' a number in the +% sequence, in which case we should use a range separator, from when they are +% after all just contiguous, in which case a pair separator is called for. +% Since, as usual, we can only know this when a arbitrary long ``streak'' +% finishes, we have to store the label which (potentially) begins a range +% (kept in \cs{l_@@_range_beg_label_tl}). \cs{l_@@_next_maybe_range_bool} +% signals when ``next'' is potentially a range with ``current'', and +% \cs{l_@@_next_is_same_bool} when their values are actually equal. +% +% +% One further thing to discuss here -- to keep this ``on record'' -- is +% inhibition of compression for individual labels. It is not difficult to +% handle it at the infrastructure side, what gets sloppy is the user facing +% syntax to signal such inhibition. For some possible alternatives for this +% (and good ones at that) see \url{https://tex.stackexchange.com/q/611370} +% (thanks Enrico Gregorio, Phelype Oleinik, and Steven B.\ Segletes). Yet +% another alternative would be an option receiving the label(s) not to be +% compressed, this would be a repetition, but would keep the syntax clean. +% All in all, probably the best is simply not to allow individual inhibition +% of compression. We can already control compression of each \cs{zcref} call +% with existing options, this should be enough. I don't think the small extra +% flexibility individual label control for this would grant is worth the +% syntax disruption it would entail. Anyway, it would be easy to deal with +% this in case the need arose, by just adding another condition (coming from +% whatever the chosen syntax was) when we check for +% \cs{@@_labels_in_sequence:nn} in \cs{@@_typeset_refs_not_last_of_type:}. +% But I remain unconvinced of the pertinence of doing so. +% +% +% \subsection*{Variables} +% +% \begin{macro} +% { +% \l_@@_typeset_labels_seq , +% \l_@@_typeset_last_bool , +% \l_@@_last_of_type_bool , +% } +% Auxiliary variables for \cs{@@_typeset_refs:} main stack control. +% \begin{macrocode} +\seq_new:N \l_@@_typeset_labels_seq +\bool_new:N \l_@@_typeset_last_bool +\bool_new:N \l_@@_last_of_type_bool +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \l_@@_type_count_int , +% \l_@@_label_count_int , +% } +% Auxiliary variables for \cs{@@_typeset_refs:} main counters. +% \begin{macrocode} +\int_new:N \l_@@_type_count_int +\int_new:N \l_@@_label_count_int +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \l_@@_label_a_tl , +% \l_@@_label_b_tl , +% \l_@@_typeset_queue_prev_tl , +% \l_@@_typeset_queue_curr_tl , +% \l_@@_type_first_label_tl , +% \l_@@_type_first_label_type_tl +% } +% Auxiliary variables for \cs{@@_typeset_refs:} main ``queue'' control and +% storage. +% \begin{macrocode} +\tl_new:N \l_@@_label_a_tl +\tl_new:N \l_@@_label_b_tl +\tl_new:N \l_@@_typeset_queue_prev_tl +\tl_new:N \l_@@_typeset_queue_curr_tl +\tl_new:N \l_@@_type_first_label_tl +\tl_new:N \l_@@_type_first_label_type_tl +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \l_@@_type_name_tl , +% \l_@@_name_in_link_bool , +% \l_@@_name_format_tl , +% \l_@@_name_format_fallback_tl , +% \l_@@_type_name_gender_tl , +% } +% Auxiliary variables for \cs{@@_typeset_refs:} type name handling. +% \begin{macrocode} +\tl_new:N \l_@@_type_name_tl +\bool_new:N \l_@@_name_in_link_bool +\tl_new:N \l_@@_name_format_tl +\tl_new:N \l_@@_name_format_fallback_tl +\tl_new:N \l_@@_type_name_gender_tl +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \l_@@_range_count_int , +% \l_@@_range_same_count_int , +% \l_@@_range_beg_label_tl , +% \l_@@_next_maybe_range_bool , +% \l_@@_next_is_same_bool , +% } +% Auxiliary variables for \cs{@@_typeset_refs:} range handling. +% \begin{macrocode} +\int_new:N \l_@@_range_count_int +\int_new:N \l_@@_range_same_count_int +\tl_new:N \l_@@_range_beg_label_tl +\bool_new:N \l_@@_next_maybe_range_bool +\bool_new:N \l_@@_next_is_same_bool +% \end{macrocode} +% \end{macro} +% +% \begin{macro} +% { +% \l_@@_tpairsep_tl , +% \l_@@_tlistsep_tl , +% \l_@@_tlastsep_tl , +% \l_@@_namesep_tl , +% \l_@@_pairsep_tl , +% \l_@@_listsep_tl , +% \l_@@_lastsep_tl , +% \l_@@_rangesep_tl , +% \l_@@_refpre_tl , +% \l_@@_refpos_tl , +% \l_@@_namefont_tl , +% \l_@@_reffont_tl , +% } +% Auxiliary variables for \cs{@@_typeset_refs:} separators, refpre/pos and +% font options. +% \begin{macrocode} +\tl_new:N \l_@@_tpairsep_tl +\tl_new:N \l_@@_tlistsep_tl +\tl_new:N \l_@@_tlastsep_tl +\tl_new:N \l_@@_namesep_tl +\tl_new:N \l_@@_pairsep_tl +\tl_new:N \l_@@_listsep_tl +\tl_new:N \l_@@_lastsep_tl +\tl_new:N \l_@@_rangesep_tl +\tl_new:N \l_@@_refpre_tl +\tl_new:N \l_@@_refpos_tl +\tl_new:N \l_@@_namefont_tl +\tl_new:N \l_@@_reffont_tl +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\l_@@_verbose_testing_bool} +% Internal variable which enables extra log messaging at points of interest +% in the code for purposes of regression testing. Particularly relevant to +% keep track of expansion control in \cs{l_@@_typeset_queue_curr_tl}. +% \begin{macrocode} +\bool_new:N \l_@@_verbose_testing_bool +% \end{macrocode} +% \end{macro} +% +% +% \subsection*{Main functions} +% +% \begin{macro}{\@@_typeset_refs:} +% Main typesetting function for \cs{zcref}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_typeset_refs: + { + \seq_set_eq:NN \l_@@_typeset_labels_seq + \l_@@_zcref_labels_seq + \tl_clear:N \l_@@_typeset_queue_prev_tl + \tl_clear:N \l_@@_typeset_queue_curr_tl + \tl_clear:N \l_@@_type_first_label_tl + \tl_clear:N \l_@@_type_first_label_type_tl + \tl_clear:N \l_@@_range_beg_label_tl + \int_zero:N \l_@@_label_count_int + \int_zero:N \l_@@_type_count_int + \int_zero:N \l_@@_range_count_int + \int_zero:N \l_@@_range_same_count_int + + % Get type block options (not type-specific). + \@@_get_ref_string:nN { tpairsep } + \l_@@_tpairsep_tl + \@@_get_ref_string:nN { tlistsep } + \l_@@_tlistsep_tl + \@@_get_ref_string:nN { tlastsep } + \l_@@_tlastsep_tl + + % Process label stack. + \bool_set_false:N \l_@@_typeset_last_bool + \bool_until_do:Nn \l_@@_typeset_last_bool + { + \seq_pop_left:NN \l_@@_typeset_labels_seq + \l_@@_label_a_tl + \seq_if_empty:NTF \l_@@_typeset_labels_seq + { + \tl_clear:N \l_@@_label_b_tl + \bool_set_true:N \l_@@_typeset_last_bool + } + { + \seq_get_left:NN \l_@@_typeset_labels_seq + \l_@@_label_b_tl + } + + \tl_if_eq:NnTF \l_@@_ref_property_tl { page } + { + \tl_set:Nn \l_@@_label_type_a_tl { page } + \tl_set:Nn \l_@@_label_type_b_tl { page } + } + { + \@@_def_extract:NVnn \l_@@_label_type_a_tl + \l_@@_label_a_tl { zc@type } { zc@missingtype } + \@@_def_extract:NVnn \l_@@_label_type_b_tl + \l_@@_label_b_tl { zc@type } { zc@missingtype } + } + + % First, we establish whether the "current label" (i.e. `a') is the + % last one of its type. This can happen because the "next label" + % (i.e. `b') is of a different type (or different definition status), + % or because we are at the end of the list. + \bool_if:NTF \l_@@_typeset_last_bool + { \bool_set_true:N \l_@@_last_of_type_bool } + { + \zref@ifrefundefined { \l_@@_label_a_tl } + { + \zref@ifrefundefined { \l_@@_label_b_tl } + { \bool_set_false:N \l_@@_last_of_type_bool } + { \bool_set_true:N \l_@@_last_of_type_bool } + } + { + \zref@ifrefundefined { \l_@@_label_b_tl } + { \bool_set_true:N \l_@@_last_of_type_bool } + { + % Neither is undefined, we must check the types. + \tl_if_eq:NNTF + \l_@@_label_type_a_tl + \l_@@_label_type_b_tl + { \bool_set_false:N \l_@@_last_of_type_bool } + { \bool_set_true:N \l_@@_last_of_type_bool } + } + } + } + + % Handle warnings in case of reference or type undefined. + % Test: 'zc-typeset01.lvt': "Typeset refs: warn ref undefined" + \zref@refused { \l_@@_label_a_tl } + % Test: 'zc-typeset01.lvt': "Typeset refs: warn missing type" + \zref@ifrefundefined { \l_@@_label_a_tl } + {} + { + \tl_if_eq:NnT \l_@@_label_type_a_tl { zc@missingtype } + { + \msg_warning:nnx { zref-clever } { missing-type } + { \l_@@_label_a_tl } + } + \zref@ifrefcontainsprop + { \l_@@_label_a_tl } + { \l_@@_ref_property_tl } + { } + { + \msg_warning:nnxx { zref-clever } { missing-property } + { \l_@@_ref_property_tl } + { \l_@@_label_a_tl } + } + } + + % Get type-specific separators, refpre/pos and font options, once per + % type. + \int_compare:nNnT { \l_@@_label_count_int } = { 0 } + { + \@@_get_ref_string:nN { namesep } + \l_@@_namesep_tl + \@@_get_ref_string:nN { pairsep } + \l_@@_pairsep_tl + \@@_get_ref_string:nN { listsep } + \l_@@_listsep_tl + \@@_get_ref_string:nN { lastsep } + \l_@@_lastsep_tl + \@@_get_ref_string:nN { rangesep } + \l_@@_rangesep_tl + \@@_get_ref_string:nN { refpre } + \l_@@_refpre_tl + \@@_get_ref_string:nN { refpos } + \l_@@_refpos_tl + \@@_get_ref_font:nN { namefont } + \l_@@_namefont_tl + \@@_get_ref_font:nN { reffont } + \l_@@_reffont_tl + } + + % Here we send this to a couple of auxiliary functions. + \bool_if:NTF \l_@@_last_of_type_bool + % There exists no next label of the same type as the current. + { \@@_typeset_refs_last_of_type: } + % There exists a next label of the same type as the current. + { \@@_typeset_refs_not_last_of_type: } + } + } +% \end{macrocode} +% \end{macro} +% +% +% This is actually the one meaningful ``big branching'' we can do while +% processing the label stack: i) the ``current'' label is the last of its type +% block; or ii) the ``current'' label is \emph{not} the last of its type +% block. Indeed, as mentioned above, quite a number of things can only be +% decided when the type block ends, and we only know this when we look at the +% ``next'' label and find something of a different ``type'' (loose here, maybe +% different definition status, maybe end of stack). So, though this is not +% very strict, \cs{@@_typeset_refs_last_of_type:} is more of a ``wrapping +% up'' function, and it is indeed the one which does the actual typesetting, +% while \cs{@@_typeset_refs_not_last_of_type:} is more of an +% ``accumulation'' function. +% +% +% \begin{macro}{\@@_typeset_refs_last_of_type:} +% Handles typesetting when the current label is the last of its type. +% \begin{macrocode} +\cs_new_protected:Npn \@@_typeset_refs_last_of_type: + { + % Process the current label to the current queue. + \int_case:nnF { \l_@@_label_count_int } + { + % It is the last label of its type, but also the first one, and that's + % what matters here: just store it. + % Test: 'zc-typeset01.lvt': "Last of type: single" + { 0 } + { + \tl_set:NV \l_@@_type_first_label_tl + \l_@@_label_a_tl + \tl_set:NV \l_@@_type_first_label_type_tl + \l_@@_label_type_a_tl + } + + % The last is the second: we have a pair (if not repeated). + % Test: 'zc-typeset01.lvt': "Last of type: pair" + { 1 } + { + \int_compare:nNnF { \l_@@_range_same_count_int } = { 1 } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_pairsep_tl + \@@_get_ref:V \l_@@_label_a_tl + } + } + } + } + % Last is third or more of its type: without repetition, we'd have the + % last element on a list, but control for possible repetition. + { + \int_case:nnF { \l_@@_range_count_int } + { + % There was no range going on. + % Test: 'zc-typeset01.lvt': "Last of type: not range" + { 0 } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_lastsep_tl + \@@_get_ref:V \l_@@_label_a_tl + } + } + % Last in the range is also the second in it. + % Test: 'zc-typeset01.lvt': "Last of type: pair in sequence" + { 1 } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + % We know `range_beg_label' is not empty, since this is the + % second element in the range, but the third or more in the + % type list. + \exp_not:V \l_@@_listsep_tl + \@@_get_ref:V \l_@@_range_beg_label_tl + \int_compare:nNnF + { \l_@@_range_same_count_int } = { 1 } + { + \exp_not:V \l_@@_lastsep_tl + \@@_get_ref:V \l_@@_label_a_tl + } + } + } + } + % Last in the range is third or more in it. + { + \int_case:nnF + { + \l_@@_range_count_int - + \l_@@_range_same_count_int + } + { + % Repetition, not a range. + % Test: 'zc-typeset01.lvt': "Last of type: range to one" + { 0 } + { + % If `range_beg_label' is empty, it means it was also the + % first of the type, and hence was already handled. + \tl_if_empty:VF \l_@@_range_beg_label_tl + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_lastsep_tl + \@@_get_ref:V + \l_@@_range_beg_label_tl + } + } + } + % A `range', but with no skipped value, treat as list. + % Test: 'zc-typeset01.lvt': "Last of type: range to pair" + { 1 } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + % Ditto. + \tl_if_empty:VF \l_@@_range_beg_label_tl + { + \exp_not:V \l_@@_listsep_tl + \@@_get_ref:V + \l_@@_range_beg_label_tl + } + \exp_not:V \l_@@_lastsep_tl + \@@_get_ref:V \l_@@_label_a_tl + } + } + } + { + % An actual range. + % Test: 'zc-typeset01.lvt': "Last of type: range" + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + % Ditto. + \tl_if_empty:VF \l_@@_range_beg_label_tl + { + \exp_not:V \l_@@_lastsep_tl + \@@_get_ref:V + \l_@@_range_beg_label_tl + } + \exp_not:V \l_@@_rangesep_tl + \@@_get_ref:V \l_@@_label_a_tl + } + } + } + } + + % Handle "range" option. The idea is simple: if the queue is not empty, + % we replace it with the end of the range (or pair). We can still + % retrieve the end of the range from `label_a' since we know to be + % processing the last label of its type at this point. + \bool_if:NT \l_@@_typeset_range_bool + { + \tl_if_empty:NTF \l_@@_typeset_queue_curr_tl + { + \zref@ifrefundefined { \l_@@_type_first_label_tl } + { } + { + \msg_warning:nnx { zref-clever } { single-element-range } + { \l_@@_type_first_label_type_tl } + } + } + { + \bool_set_false:N \l_@@_next_maybe_range_bool + \zref@ifrefundefined { \l_@@_type_first_label_tl } + { } + { + \@@_labels_in_sequence:nn + { \l_@@_type_first_label_tl } + { \l_@@_label_a_tl } + } + % Test: 'zc-typeset01.lvt': "Last of type: option range" + % Test: 'zc-typeset01.lvt': "Last of type: option range to pair" + \tl_set:Nx \l_@@_typeset_queue_curr_tl + { + \bool_if:NTF \l_@@_next_maybe_range_bool + { \exp_not:V \l_@@_pairsep_tl } + { \exp_not:V \l_@@_rangesep_tl } + \@@_get_ref:V \l_@@_label_a_tl + } + } + } + + % Now that the type block is finished, we can add the name and the first + % ref to the queue. Also, if "typeset" option is not "both", handle it + % here as well. + \@@_type_name_setup: + \bool_if:nTF + { \l_@@_typeset_ref_bool && \l_@@_typeset_name_bool } + { + \tl_put_left:Nx \l_@@_typeset_queue_curr_tl + { \@@_get_ref_first: } + } + { + \bool_if:NTF \l_@@_typeset_ref_bool + { + % Test: 'zc-typeset01.lvt': "Last of type: option typeset ref" + \tl_put_left:Nx \l_@@_typeset_queue_curr_tl + { \@@_get_ref:V \l_@@_type_first_label_tl } + } + { + \bool_if:NTF \l_@@_typeset_name_bool + { + % Test: 'zc-typeset01.lvt': "Last of type: option typeset name" + \tl_set:Nx \l_@@_typeset_queue_curr_tl + { + \bool_if:NTF \l_@@_name_in_link_bool + { + \exp_not:N \group_begin: + \exp_not:V \l_@@_namefont_tl + % It's two '@s', but escaped for DocStrip. + \exp_not:N \hyper@@@@link + { + \@@_extract_url_unexp:V + \l_@@_type_first_label_tl + } + { + \@@_extract_unexp:Vnn + \l_@@_type_first_label_tl + { anchor } { } + } + { \exp_not:V \l_@@_type_name_tl } + \exp_not:N \group_end: + } + { + \exp_not:N \group_begin: + \exp_not:V \l_@@_namefont_tl + \exp_not:V \l_@@_type_name_tl + \exp_not:N \group_end: + } + } + } + { + % Logically, this case would correspond to "typeset=none", but + % it should not occur, given that the options are set up to + % typeset either "ref" or "name". Still, leave here a + % sensible fallback, equal to the behavior of "both". + % Test: 'zc-typeset01.lvt': "Last of type: option typeset none" + \tl_put_left:Nx \l_@@_typeset_queue_curr_tl + { \@@_get_ref_first: } + } + } + } + + % Typeset the previous type block, if there is one. + \int_compare:nNnT { \l_@@_type_count_int } > { 0 } + { + \int_compare:nNnT { \l_@@_type_count_int } > { 1 } + { \l_@@_tlistsep_tl } + \l_@@_typeset_queue_prev_tl + } + + % Extra log for testing. + \bool_if:NT \l_@@_verbose_testing_bool + { \tl_show:N \l_@@_typeset_queue_curr_tl } + + % Wrap up loop, or prepare for next iteration. + \bool_if:NTF \l_@@_typeset_last_bool + { + % We are finishing, typeset the current queue. + \int_case:nnF { \l_@@_type_count_int } + { + % Single type. + % Test: 'zc-typeset01.lvt': "Last of type: single type" + { 0 } + { \l_@@_typeset_queue_curr_tl } + % Pair of types. + % Test: 'zc-typeset01.lvt': "Last of type: pair of types" + { 1 } + { + \l_@@_tpairsep_tl + \l_@@_typeset_queue_curr_tl + } + } + { + % Last in list of types. + % Test: 'zc-typeset01.lvt': "Last of type: list of types" + \l_@@_tlastsep_tl + \l_@@_typeset_queue_curr_tl + } + % And nudge in case of multitype reference. + \bool_lazy_all:nT + { + { \l_@@_nudge_enabled_bool } + { \l_@@_nudge_multitype_bool } + { \int_compare_p:nNn { \l_@@_type_count_int } > { 0 } } + } + { \msg_warning:nn { zref-clever } { nudge-multitype } } + } + { + % There are further labels, set variables for next iteration. + \tl_set_eq:NN \l_@@_typeset_queue_prev_tl + \l_@@_typeset_queue_curr_tl + \tl_clear:N \l_@@_typeset_queue_curr_tl + \tl_clear:N \l_@@_type_first_label_tl + \tl_clear:N \l_@@_type_first_label_type_tl + \tl_clear:N \l_@@_range_beg_label_tl + \int_zero:N \l_@@_label_count_int + \int_incr:N \l_@@_type_count_int + \int_zero:N \l_@@_range_count_int + \int_zero:N \l_@@_range_same_count_int + } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_typeset_refs_not_last_of_type:} +% Handles typesetting when the current label is not the last of its type. +% \begin{macrocode} +\cs_new_protected:Npn \@@_typeset_refs_not_last_of_type: + { + % Signal if next label may form a range with the current one (only + % considered if compression is enabled in the first place). + \bool_set_false:N \l_@@_next_maybe_range_bool + \bool_set_false:N \l_@@_next_is_same_bool + \bool_if:NT \l_@@_typeset_compress_bool + { + \zref@ifrefundefined { \l_@@_label_a_tl } + { } + { + \@@_labels_in_sequence:nn + { \l_@@_label_a_tl } { \l_@@_label_b_tl } + } + } + + % Process the current label to the current queue. + \int_compare:nNnTF { \l_@@_label_count_int } = { 0 } + { + % Current label is the first of its type (also not the last, but it + % doesn't matter here): just store the label. + \tl_set:NV \l_@@_type_first_label_tl + \l_@@_label_a_tl + \tl_set:NV \l_@@_type_first_label_type_tl + \l_@@_label_type_a_tl + + % If the next label may be part of a range, we set `range_beg_label' + % to "empty" (we deal with it as the "first", and must do it there, to + % handle hyperlinking), but also step the range counters. + % Test: 'zc-typeset01.lvt': "Not last of type: first is range" + \bool_if:NT \l_@@_next_maybe_range_bool + { + \tl_clear:N \l_@@_range_beg_label_tl + \int_incr:N \l_@@_range_count_int + \bool_if:NT \l_@@_next_is_same_bool + { \int_incr:N \l_@@_range_same_count_int } + } + } + { + % Current label is neither the first (nor the last) of its type. + \bool_if:NTF \l_@@_next_maybe_range_bool + { + % Starting, or continuing a range. + \int_compare:nNnTF + { \l_@@_range_count_int } = { 0 } + { + % There was no range going, we are starting one. + \tl_set:NV \l_@@_range_beg_label_tl + \l_@@_label_a_tl + \int_incr:N \l_@@_range_count_int + \bool_if:NT \l_@@_next_is_same_bool + { \int_incr:N \l_@@_range_same_count_int } + } + { + % Second or more in the range, but not the last. + \int_incr:N \l_@@_range_count_int + \bool_if:NT \l_@@_next_is_same_bool + { \int_incr:N \l_@@_range_same_count_int } + } + } + { + % Next element is not in sequence: there was no range, or we are + % closing one. + \int_case:nnF { \l_@@_range_count_int } + { + % There was no range going on. + % Test: 'zc-typeset01.lvt': "Not last of type: no range" + { 0 } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \exp_not:V \l_@@_listsep_tl + \@@_get_ref:V \l_@@_label_a_tl + } + } + % Last is second in the range: if `range_same_count' is also + % `1', it's a repetition (drop it), otherwise, it's a "pair + % within a list", treat as list. + % Test: 'zc-typeset01.lvt': "Not last of type: range pair to one" + % Test: 'zc-typeset01.lvt': "Not last of type: range pair" + { 1 } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \tl_if_empty:VF \l_@@_range_beg_label_tl + { + \exp_not:V \l_@@_listsep_tl + \@@_get_ref:V + \l_@@_range_beg_label_tl + } + \int_compare:nNnF + { \l_@@_range_same_count_int } = { 1 } + { + \exp_not:V \l_@@_listsep_tl + \@@_get_ref:V + \l_@@_label_a_tl + } + } + } + } + { + % Last is third or more in the range: if `range_count' and + % `range_same_count' are the same, its a repetition (drop it), + % if they differ by `1', its a list, if they differ by more, + % it is a real range. + \int_case:nnF + { + \l_@@_range_count_int - + \l_@@_range_same_count_int + } + { + % Test: 'zc-typeset01.lvt': "Not last of type: range to one" + { 0 } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \tl_if_empty:VF \l_@@_range_beg_label_tl + { + \exp_not:V \l_@@_listsep_tl + \@@_get_ref:V + \l_@@_range_beg_label_tl + } + } + } + % Test: 'zc-typeset01.lvt': "Not last of type: range to pair" + { 1 } + { + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \tl_if_empty:VF \l_@@_range_beg_label_tl + { + \exp_not:V \l_@@_listsep_tl + \@@_get_ref:V + \l_@@_range_beg_label_tl + } + \exp_not:V \l_@@_listsep_tl + \@@_get_ref:V \l_@@_label_a_tl + } + } + } + { + % Test: 'zc-typeset01.lvt': "Not last of type: range" + \tl_put_right:Nx \l_@@_typeset_queue_curr_tl + { + \tl_if_empty:VF \l_@@_range_beg_label_tl + { + \exp_not:V \l_@@_listsep_tl + \@@_get_ref:V + \l_@@_range_beg_label_tl + } + \exp_not:V \l_@@_rangesep_tl + \@@_get_ref:V \l_@@_label_a_tl + } + } + } + % Reset counters. + \int_zero:N \l_@@_range_count_int + \int_zero:N \l_@@_range_same_count_int + } + } + % Step label counter for next iteration. + \int_incr:N \l_@@_label_count_int + } +% \end{macrocode} +% \end{macro} +% +% +% +% \subsection*{Auxiliary functions} +% +% \cs{@@_get_ref:n} and \cs{@@_get_ref_first:} are the two functions which +% actually build the reference blocks for typesetting. \cs{@@_get_ref:n} +% handles all references but the first of its type, and \cs{@@_get_ref_first:} +% deals with the first reference of a type. Saying they do ``typesetting'' is +% imprecise though, they actually prepare material to be accumulated in +% \cs{l_@@_typeset_queue_curr_tl} inside \cs{@@_typeset_refs_last_of_type:} +% and \cs{@@_typeset_refs_not_last_of_type:}. And this difference results +% quite crucial for the \TeX{}nical requirements of these functions. This +% because, as we are processing the label stack and accumulating content in +% the queue, we are using a number of variables which are transient to the +% current label, the label properties among them, but not only. Hence, these +% variables \emph{must} be expanded to their current values to be stored in +% the queue. Indeed, \cs{@@_get_ref:n} and \cs{@@_get_ref_first:} get called, +% as they must, in the context of \texttt{x} type expansions. But we don't +% want to expand the values of the variables themselves, so we need to get +% current values, but stop expansion after that. In particular, reference +% options given by the user should reach the stream for its final typesetting +% (when the queue itself gets typeset) \emph{unmodified} (``no manipulation'', +% to use the \texttt{n} signature jargon). We also need to prevent premature +% expansion of material that can't be expanded at this point (e.g. grouping, +% \cs{zref@default} or \cs[replace=false]{hyper@@link}). In a nutshell, the +% job of these two functions is putting the pieces in place, but with proper +% expansion control. +% +% +% \begin{macro}{\@@_ref_default:, \@@_name_default:} +% Default values for undefined references and undefined type names, +% respectively. We are ultimately using \cs{zref@default}, but calls to it +% should be made through these internal functions, according to the case. +% As a bonus, we don't need to protect them with \cs{exp_not:N}, as +% \cs{zref@default} would require, since we already define them protected. +% \begin{macrocode} +\cs_new_protected:Npn \@@_ref_default: + { \zref@default } +\cs_new_protected:Npn \@@_name_default: + { \zref@default } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_get_ref:n} +% Handles a complete reference block to be accumulated in the ``queue'', +% including ``pre'' and ``pos'' elements, and hyperlinking. For use with +% all labels, except the first of its type, which is done by +% \cs{@@_get_ref_first:}. +% \begin{syntax} +% \cs{@@_get_ref:n} \Arg{label} +% \end{syntax} +% \begin{macrocode} +\cs_new:Npn \@@_get_ref:n #1 + { + \zref@ifrefcontainsprop {#1} { \l_@@_ref_property_tl } + { + \bool_if:nTF + { + \l_@@_use_hyperref_bool && + ! \l_@@_link_star_bool + } + { + \bool_if:NF \l_@@_preposinlink_bool + { \exp_not:V \l_@@_refpre_tl } + % It's two `@s', but escaped for DocStrip. + \exp_not:N \hyper@@@@link + { \@@_extract_url_unexp:n {#1} } + { \@@_extract_unexp:nnn {#1} { anchor } { } } + { + \bool_if:NT \l_@@_preposinlink_bool + { \exp_not:V \l_@@_refpre_tl } + \exp_not:N \group_begin: + \exp_not:V \l_@@_reffont_tl + \@@_extract_unexp:nvn {#1} + { l_@@_ref_property_tl } { } + \exp_not:N \group_end: + \bool_if:NT \l_@@_preposinlink_bool + { \exp_not:V \l_@@_refpos_tl } + } + \bool_if:NF \l_@@_preposinlink_bool + { \exp_not:V \l_@@_refpos_tl } + } + { + \exp_not:V \l_@@_refpre_tl + \exp_not:N \group_begin: + \exp_not:V \l_@@_reffont_tl + \@@_extract_unexp:nvn {#1} + { l_@@_ref_property_tl } { } + \exp_not:N \group_end: + \exp_not:V \l_@@_refpos_tl + } + } + { \@@_ref_default: } + } +\cs_generate_variant:Nn \@@_get_ref:n { V } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_get_ref_first:} +% Handles a complete reference block for the first label of its type to be +% accumulated in the ``queue'', including ``pre'' and ``pos'' elements, +% hyperlinking, and the reference type ``name''. It does not receive +% arguments, but relies on being called in the appropriate place in +% \cs{@@_typeset_refs_last_of_type:} where a number of variables are +% expected to be appropriately set for it to consume. Prominently among +% those is \cs{l_@@_type_first_label_tl}, but it also expected to be called +% right after \cs{@@_type_name_setup:} which sets \cs{l_@@_type_name_tl} and +% \cs{l_@@_name_in_link_bool} which it uses. +% \begin{macrocode} +\cs_new:Npn \@@_get_ref_first: + { + \zref@ifrefundefined { \l_@@_type_first_label_tl } + { \@@_ref_default: } + { + \bool_if:NTF \l_@@_name_in_link_bool + { + \zref@ifrefcontainsprop + { \l_@@_type_first_label_tl } + { \l_@@_ref_property_tl } + { + % It's two `@s', but escaped for DocStrip. + \exp_not:N \hyper@@@@link + { + \@@_extract_url_unexp:V + \l_@@_type_first_label_tl + } + { + \@@_extract_unexp:Vnn + \l_@@_type_first_label_tl { anchor } { } + } + { + \exp_not:N \group_begin: + \exp_not:V \l_@@_namefont_tl + \exp_not:V \l_@@_type_name_tl + \exp_not:N \group_end: + \exp_not:V \l_@@_namesep_tl + \exp_not:V \l_@@_refpre_tl + \exp_not:N \group_begin: + \exp_not:V \l_@@_reffont_tl + \@@_extract_unexp:Vvn + \l_@@_type_first_label_tl + { l_@@_ref_property_tl } { } + \exp_not:N \group_end: + \bool_if:NT \l_@@_preposinlink_bool + { \exp_not:V \l_@@_refpos_tl } + } + \bool_if:NF \l_@@_preposinlink_bool + { \exp_not:V \l_@@_refpos_tl } + } + { + \exp_not:N \group_begin: + \exp_not:V \l_@@_namefont_tl + \exp_not:V \l_@@_type_name_tl + \exp_not:N \group_end: + \exp_not:V \l_@@_namesep_tl + \@@_ref_default: + } + } + { + \tl_if_empty:NTF \l_@@_type_name_tl + { + \@@_name_default: + \exp_not:V \l_@@_namesep_tl + } + { + \exp_not:N \group_begin: + \exp_not:V \l_@@_namefont_tl + \exp_not:V \l_@@_type_name_tl + \exp_not:N \group_end: + \exp_not:V \l_@@_namesep_tl + } + \zref@ifrefcontainsprop + { \l_@@_type_first_label_tl } + { \l_@@_ref_property_tl } + { + \bool_if:nTF + { + \l_@@_use_hyperref_bool && + ! \l_@@_link_star_bool + } + { + \bool_if:NF \l_@@_preposinlink_bool + { \exp_not:V \l_@@_refpre_tl } + % It's two '@s', but escaped for DocStrip. + \exp_not:N \hyper@@@@link + { + \@@_extract_url_unexp:V + \l_@@_type_first_label_tl + } + { + \@@_extract_unexp:Vnn + \l_@@_type_first_label_tl { anchor } { } + } + { + \bool_if:NT \l_@@_preposinlink_bool + { \exp_not:V \l_@@_refpre_tl } + \exp_not:N \group_begin: + \exp_not:V \l_@@_reffont_tl + \@@_extract_unexp:Vvn + \l_@@_type_first_label_tl + { l_@@_ref_property_tl } { } + \exp_not:N \group_end: + \bool_if:NT \l_@@_preposinlink_bool + { \exp_not:V \l_@@_refpos_tl } + } + \bool_if:NF \l_@@_preposinlink_bool + { \exp_not:V \l_@@_refpos_tl } + } + { + \exp_not:V \l_@@_refpre_tl + \exp_not:N \group_begin: + \exp_not:V \l_@@_reffont_tl + \@@_extract_unexp:Vvn + \l_@@_type_first_label_tl + { l_@@_ref_property_tl } { } + \exp_not:N \group_end: + \exp_not:V \l_@@_refpos_tl + } + } + { \@@_ref_default: } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_type_name_setup:} +% Auxiliary function to \cs{@@_typeset_refs_last_of_type:}. It is +% responsible for setting the type name variable \cs{l_@@_type_name_tl} and +% \cs{l_@@_name_in_link_bool}. If a type name can't be found, +% \cs{l_@@_type_name_tl} is cleared. The function takes no arguments, but +% is expected to be called in \cs{@@_typeset_refs_last_of_type:} right +% before \cs{@@_get_ref_first:}, which is the main consumer of the variables +% it sets, though not the only one (and hence this cannot be moved into +% \cs{@@_get_ref_first:} itself). It also expects a number of relevant +% variables to have been appropriately set, and which it uses, prominently +% \cs{l_@@_type_first_label_type_tl}, but also the queue itself in +% \cs{l_@@_typeset_queue_curr_tl}, which should be ``ready except for the +% first label'', and the type counter \cs{l_@@_type_count_int}. +% \begin{macrocode} +\cs_new_protected:Npn \@@_type_name_setup: + { + \zref@ifrefundefined { \l_@@_type_first_label_tl } + { \tl_clear:N \l_@@_type_name_tl } + { + \tl_if_eq:NnTF + \l_@@_type_first_label_type_tl { zc@missingtype } + { \tl_clear:N \l_@@_type_name_tl } + { + % Determine whether we should use capitalization, abbreviation, + % and plural. + \bool_lazy_or:nnTF + { \l_@@_capitalize_bool } + { + \l_@@_capitalize_first_bool && + \int_compare_p:nNn { \l_@@_type_count_int } = { 0 } + } + { \tl_set:Nn \l_@@_name_format_tl {Name} } + { \tl_set:Nn \l_@@_name_format_tl {name} } + % If the queue is empty, we have a singular, otherwise, plural. + \tl_if_empty:NTF \l_@@_typeset_queue_curr_tl + { \tl_put_right:Nn \l_@@_name_format_tl { -sg } } + { \tl_put_right:Nn \l_@@_name_format_tl { -pl } } + \bool_lazy_and:nnTF + { \l_@@_abbrev_bool } + { + ! \int_compare_p:nNn + { \l_@@_type_count_int } = { 0 } || + ! \l_@@_noabbrev_first_bool + } + { + \tl_set:NV \l_@@_name_format_fallback_tl + \l_@@_name_format_tl + \tl_put_right:Nn \l_@@_name_format_tl { -ab } + } + { \tl_clear:N \l_@@_name_format_fallback_tl } + + % Handle number and gender nudges. + \bool_if:NT \l_@@_nudge_enabled_bool + { + \bool_if:NTF \l_@@_nudge_singular_bool + { + \tl_if_empty:NF \l_@@_typeset_queue_curr_tl + { + \msg_warning:nnx { zref-clever } + { nudge-plural-when-sg } + { \l_@@_type_first_label_type_tl } + } + } + { + \bool_lazy_all:nT + { + { \l_@@_nudge_comptosing_bool } + { \tl_if_empty_p:N \l_@@_typeset_queue_curr_tl } + { + \int_compare_p:nNn + { \l_@@_label_count_int } > { 0 } + } + } + { + \msg_warning:nnx { zref-clever } + { nudge-comptosing } + { \l_@@_type_first_label_type_tl } + } + } + \bool_lazy_and:nnT + { \l_@@_nudge_gender_bool } + { ! \tl_if_empty_p:N \l_@@_ref_gender_tl } + { + \@@_get_type_transl:xxnNF + { \l_@@_ref_language_tl } + { \l_@@_type_first_label_type_tl } + { gender } + \l_@@_type_name_gender_tl + { \tl_clear:N \l_@@_type_name_gender_tl } + \tl_if_eq:NNF + \l_@@_ref_gender_tl + \l_@@_type_name_gender_tl + { + \tl_if_empty:NTF \l_@@_type_name_gender_tl + { + \msg_warning:nnxxx { zref-clever } + { nudge-gender-not-declared-for-type } + { \l_@@_ref_gender_tl } + { \l_@@_type_first_label_type_tl } + { \l_@@_ref_language_tl } + } + { + \msg_warning:nnxxxx { zref-clever } + { nudge-gender-mismatch } + { \l_@@_type_first_label_type_tl } + { \l_@@_ref_gender_tl } + { \l_@@_type_name_gender_tl } + { \l_@@_ref_language_tl } + } + } + } + } + + \tl_if_empty:NTF \l_@@_name_format_fallback_tl + { + \prop_get:cVNF + { + l_@@_type_ + \l_@@_type_first_label_type_tl _options_prop + } + \l_@@_name_format_tl + \l_@@_type_name_tl + { + \tl_if_empty:NF \l_@@_ref_decl_case_tl + { + \tl_put_left:Nn \l_@@_name_format_tl { - } + \tl_put_left:NV \l_@@_name_format_tl + \l_@@_ref_decl_case_tl + } + \@@_get_type_transl:xxxNF + { \l_@@_ref_language_tl } + { \l_@@_type_first_label_type_tl } + { \l_@@_name_format_tl } + \l_@@_type_name_tl + { + \tl_clear:N \l_@@_type_name_tl + \msg_warning:nnxx { zref-clever } { missing-name } + { \l_@@_name_format_tl } + { \l_@@_type_first_label_type_tl } + } + } + } + { + \prop_get:cVNF + { + l_@@_type_ + \l_@@_type_first_label_type_tl _options_prop + } + \l_@@_name_format_tl + \l_@@_type_name_tl + { + \prop_get:cVNF + { + l_@@_type_ + \l_@@_type_first_label_type_tl _options_prop + } + \l_@@_name_format_fallback_tl + \l_@@_type_name_tl + { + \tl_if_empty:NF \l_@@_ref_decl_case_tl + { + \tl_put_left:Nn + \l_@@_name_format_tl { - } + \tl_put_left:NV \l_@@_name_format_tl + \l_@@_ref_decl_case_tl + \tl_put_left:Nn + \l_@@_name_format_fallback_tl { - } + \tl_put_left:NV + \l_@@_name_format_fallback_tl + \l_@@_ref_decl_case_tl + } + \@@_get_type_transl:xxxNF + { \l_@@_ref_language_tl } + { \l_@@_type_first_label_type_tl } + { \l_@@_name_format_tl } + \l_@@_type_name_tl + { + \@@_get_type_transl:xxxNF + { \l_@@_ref_language_tl } + { \l_@@_type_first_label_type_tl } + { \l_@@_name_format_fallback_tl } + \l_@@_type_name_tl + { + \tl_clear:N \l_@@_type_name_tl + \msg_warning:nnxx { zref-clever } + { missing-name } + { \l_@@_name_format_tl } + { \l_@@_type_first_label_type_tl } + } + } + } + } + } + } + } + + % Signal whether the type name is to be included in the hyperlink or not. + \bool_lazy_any:nTF + { + { ! \l_@@_use_hyperref_bool } + { \l_@@_link_star_bool } + { \tl_if_empty_p:N \l_@@_type_name_tl } + { \str_if_eq_p:Vn \l_@@_nameinlink_str { false } } + } + { \bool_set_false:N \l_@@_name_in_link_bool } + { + \bool_lazy_any:nTF + { + { \str_if_eq_p:Vn \l_@@_nameinlink_str { true } } + { + \str_if_eq_p:Vn \l_@@_nameinlink_str { tsingle } && + \tl_if_empty_p:N \l_@@_typeset_queue_curr_tl + } + { + \str_if_eq_p:Vn \l_@@_nameinlink_str { single } && + \tl_if_empty_p:N \l_@@_typeset_queue_curr_tl && + \l_@@_typeset_last_bool && + \int_compare_p:nNn { \l_@@_type_count_int } = { 0 } + } + } + { \bool_set_true:N \l_@@_name_in_link_bool } + { \bool_set_false:N \l_@@_name_in_link_bool } + } + } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_extract_url_unexp:n} +% A convenience auxiliary function for extraction of the \texttt{url} / +% \texttt{urluse} property, provided by the \pkg{zref-xr} module. Ensure +% that, in the context of an x expansion, \cs{zref@extractdefault} is +% expanded exactly twice, but no further to retrieve the proper value. See +% documentation for \cs{@@_extract_unexp:nnn}. +% \begin{macrocode} +\cs_new:Npn \@@_extract_url_unexp:n #1 + { + \zref@ifpropundefined { urluse } + { \@@_extract_unexp:nnn {#1} { url } { \c_empty_tl } } + { + \zref@ifrefcontainsprop {#1} { urluse } + { \@@_extract_unexp:nnn {#1} { urluse } { \c_empty_tl } } + { \@@_extract_unexp:nnn {#1} { url } { \c_empty_tl } } + } + } +\cs_generate_variant:Nn \@@_extract_url_unexp:n { V } +% \end{macrocode} +% \end{macro} +% +% +% \begin{macro}{\@@_labels_in_sequence:nn} +% Auxiliary function to \cs{@@_typeset_refs_not_last_of_type:}. Sets +% \cs{l_@@_next_maybe_range_bool} to true if \meta{label b} comes in +% immediate sequence from \meta{label a}. And sets both +% \cs{l_@@_next_maybe_range_bool} and \cs{l_@@_next_is_same_bool} to true if +% the two labels are the ``same'' (that is, have the same counter value). +% These two boolean variables are the basis for all range and compression +% handling inside \cs{@@_typeset_refs_not_last_of_type:}, so this function +% is expected to be called at its beginning, if compression is enabled. +% \begin{syntax} +% \cs{@@_labels_in_sequence:nn} \Arg{label a} \Arg{label b} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_labels_in_sequence:nn #1#2 + { + \@@_def_extract:Nnnn \l_@@_label_extdoc_a_tl + {#1} { externaldocument } { \c_empty_tl } + \@@_def_extract:Nnnn \l_@@_label_extdoc_b_tl + {#2} { externaldocument } { \c_empty_tl } + + \tl_if_eq:NNT + \l_@@_label_extdoc_a_tl + \l_@@_label_extdoc_b_tl + { + \tl_if_eq:NnTF \l_@@_ref_property_tl { page } + { + \exp_args:Nxx \tl_if_eq:nnT + { \@@_extract_unexp:nnn {#1} { zc@pgfmt } { } } + { \@@_extract_unexp:nnn {#2} { zc@pgfmt } { } } + { + \int_compare:nNnTF + { \@@_extract:nnn {#1} { zc@pgval } { -2 } + 1 } + = + { \@@_extract:nnn {#2} { zc@pgval } { -1 } } + { \bool_set_true:N \l_@@_next_maybe_range_bool } + { + \int_compare:nNnT + { \@@_extract:nnn {#1} { zc@pgval } { -1 } } + = + { \@@_extract:nnn {#2} { zc@pgval } { -1 } } + { + \bool_set_true:N \l_@@_next_maybe_range_bool + \bool_set_true:N \l_@@_next_is_same_bool + } + } + } + } + { + \exp_args:Nxx \tl_if_eq:nnT + { \@@_extract_unexp:nnn {#1} { zc@counter } { } } + { \@@_extract_unexp:nnn {#2} { zc@counter } { } } + { + \exp_args:Nxx \tl_if_eq:nnT + { \@@_extract_unexp:nnn {#1} { zc@enclval } { } } + { \@@_extract_unexp:nnn {#2} { zc@enclval } { } } + { + \int_compare:nNnTF + { \@@_extract:nnn {#1} { zc@cntval } { -2 } + 1 } + = + { \@@_extract:nnn {#2} { zc@cntval } { -1 } } + { \bool_set_true:N \l_@@_next_maybe_range_bool } + { + \int_compare:nNnT + { \@@_extract:nnn {#1} { zc@cntval } { -1 } } + = + { \@@_extract:nnn {#2} { zc@cntval } { -1 } } + { + \bool_set_true:N + \l_@@_next_maybe_range_bool + \exp_args:Nxx \tl_if_eq:nnT + { + \@@_extract_unexp:nvn {#1} + { l_@@_ref_property_tl } { } + } + { + \@@_extract_unexp:nvn {#2} + { l_@@_ref_property_tl } { } + } + { + \bool_set_true:N + \l_@@_next_is_same_bool + } + } + } + } + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% +% +% Finally, a couple of functions for retrieving options values, according to +% the relevant precedence rules. They both receive an \meta{option} as +% argument, and store the retrieved value in \meta{tl variable}. Though these +% are mostly general functions (for a change\dots{}), they are not completely +% so, they rely on the current state of \cs{l_@@_label_type_a_tl}, as set +% during the processing of the label stack. This could be easily generalized, +% of course, but I don't think it is worth it, \cs{l_@@_label_type_a_tl} is +% indeed what we want in all practical cases. The difference between +% \cs{@@_get_ref_string:nN} and \cs{@@_get_ref_font:nN} is the kind of option +% each should be used for. \cs{@@_get_ref_string:nN} is meant for the general +% options, and attempts to find values for them in all precedence levels (four +% plus ``fallback''). \cs{@@_get_ref_font:nN} is intended for ``font'' +% options, which cannot be ``language-specific'', thus for these we just +% search general options and type options. +% +% \begin{macro}{\@@_get_ref_string:nN} +% \begin{syntax} +% \cs{@@_get_ref_string:nN} \Arg{option} \Arg{tl variable} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_get_ref_string:nN #1#2 + { + % First attempt: general options. + \prop_get:NnNF \l_@@_ref_options_prop {#1} #2 + { + % If not found, try type specific options. + \bool_lazy_and:nnTF + { + \prop_if_exist_p:c + { + l_@@_type_ + \l_@@_label_type_a_tl _options_prop + } + } + { + \prop_if_in_p:cn + { + l_@@_type_ + \l_@@_label_type_a_tl _options_prop + } + {#1} + } + { + \prop_get:cnN + { + l_@@_type_ + \l_@@_label_type_a_tl _options_prop + } + {#1} #2 + } + { + % If not found, try type specific translations. + \@@_get_type_transl:xxnNF + { \l_@@_ref_language_tl } + { \l_@@_label_type_a_tl } + {#1} #2 + { + % If not found, try default translations. + \@@_get_default_transl:xnNF + { \l_@@_ref_language_tl } + {#1} #2 + { + % If not found, try fallback. + \@@_get_fallback_transl:nNF {#1} #2 + { + \tl_clear:N #2 + \msg_warning:nnn { zref-clever } + { missing-string } {#1} + } + } + } + } + } + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\@@_get_ref_font:nN} +% \begin{syntax} +% \cs{@@_get_ref_font:nN} \Arg{option} \Arg{tl variable} +% \end{syntax} +% \begin{macrocode} +\cs_new_protected:Npn \@@_get_ref_font:nN #1#2 + { + % First attempt: general options. + \prop_get:NnNF \l_@@_ref_options_prop {#1} #2 + { + % If not found, try type specific options. + \bool_if:nTF + { + \prop_if_exist_p:c + { + l_@@_type_ + \l_@@_label_type_a_tl _options_prop + } + } + { + \prop_get:cnNF + { + l_@@_type_ + \l_@@_label_type_a_tl _options_prop + } + {#1} #2 + { \tl_clear:N #2 } + } + { \tl_clear:N #2 } + } + } +% \end{macrocode} +% \end{macro} +% +% +% +% \section{Compatibility} +% +% This section is meant to aggregate any ``special handling'' needed for +% \LaTeX{} kernel features, document classes, and packages, needed for +% \pkg{zref-clever} to work properly with them. +% +% +% \subsection{\opt{appendix}} +% +% One relevant case of different reference types sharing the same counter is +% the \cs{appendix} which in some document classes, including the standard +% ones, change the sectioning commands looks but, of course, keep using the +% same counter. \file{book.cls} and \file{report.cls} reset counters +% \texttt{chapter} and \texttt{section} to 0, change \cs{@chapapp} to use +% \cs{appendixname} and use \cs{@Alph} for \cs{thechapter}. \file{article.cls} +% resets counters \texttt{section} and \texttt{subsection} to 0, and uses +% \cs{@Alph} for \cs{thesection}. \file{memoir.cls}, \file{scrbook.cls} and +% \file{scrarticle.cls} do the same as their corresponding standard classes, +% and sometimes a little more, but what interests us here is pretty much the +% same. See also the \pkg{appendix} package. +% +% The standard \cs{appendix} command is a one way switch, in other words, it +% cannot be reverted (see \url{https://tex.stackexchange.com/a/444057}). So, +% even if the fact that it is a ``switch'' rather than an environment +% complicates things, because we have to make ungrouped settings to correspond +% to its effects, in practice this is not a big deal, since these settings are +% never really reverted (by default, at least). Hence, hooking into +% \cs{appendix} is a viable and natural alternative. The \cls{memoir} class +% and the \pkg{appendix} package define the \texttt{appendices} and +% \texttt{subappendices} environments, which provide for a way for the +% appendix to ``end'', but in this case, of course, we can hook into the +% environment instead. +% +% \begin{macrocode} +\@@_compat_module:nn { appendix } + { + \AddToHook { cmd / appendix / before } + { + \@@_zcsetup:n + { + countertype = + { + chapter = appendix , + section = appendix , + subsection = appendix , + subsubsection = appendix , + paragraph = appendix , + subparagraph = appendix , + } + } + } + } +% \end{macrocode} +% +% Depending on the definition of \cs{appendix}, using the hook may lead to +% trouble with the first released version of \pkg{ltcmdhooks} (the one +% released with the 2021-06-01 kernel). Particularly, if the definition of +% the command being hooked at contains a double hash mark (\texttt{\#\#}) the +% patch to add the hook, if it needs to be done with the \cs{scantokens} +% method, may fail noisily (see \url{https://tex.stackexchange.com/q/617905}, +% thanks Phelype Oleinik). The 2021-11-15 kernel release already handle this +% gracefully (see \url{https://github.com/latex3/latex2e/pull/699}, thanks +% Phelype Oleinik). +% +% +% \subsection{\opt{appendices}} +% +% This module applies both to the \pkg{appendix} package, and to the +% \cls{memoir} class, since it ``emulates'' the package. +% +% \begin{macrocode} +\@@_compat_module:nn { appendices } + { + \@@_if_package_loaded:nT { appendix } + { + \newcounter { zc@appendix } + \newcounter { zc@save@appendix } + \setcounter { zc@appendix } { 0 } + \setcounter { zc@save@appendix } { 0 } + \cs_if_exist:cTF { chapter } + { + \@@_zcsetup:n + { counterresetby = { chapter = zc@appendix } } + } + { + \cs_if_exist:cT { section } + { + \@@_zcsetup:n + { counterresetby = { section = zc@appendix } } + } + } + \AddToHook { env / appendices / begin } + { + \stepcounter { zc@save@appendix } + \setcounter { zc@appendix } { \value { zc@save@appendix } } + \@@_zcsetup:n + { + countertype = + { + chapter = appendix , + section = appendix , + subsection = appendix , + subsubsection = appendix , + paragraph = appendix , + subparagraph = appendix , + } + } + } + \AddToHook { env / appendices / end } + { \setcounter { zc@appendix } { 0 } } + \AddToHook { cmd / appendix / before } + { + \stepcounter { zc@save@appendix } + \setcounter { zc@appendix } { \value { zc@save@appendix } } + } + \AddToHook { env / subappendices / begin } + { + \@@_zcsetup:n + { + countertype = + { + section = appendix , + subsection = appendix , + subsubsection = appendix , + paragraph = appendix , + subparagraph = appendix , + } , + } + } + \msg_info:nnn { zref-clever } { compat-package } { appendix } + } + } +% \end{macrocode} +% +% +% +% \subsection{\opt{memoir}} +% +% The \cls{memoir} document class has quite a number of cross-referencing +% related features, mostly dealing with captions, subfloats, and notes. Some +% of them are implemented in ways which make difficult the use of \pkg{zref}, +% particularly \cs{zlabel}, short of redefining the whole stuff ourselves. +% Hopefully, these features are specialized enough to make \pkg{zref-clever} +% useful enough with \cls{memoir} without much friction, but unless some +% support is added upstream, it is difficult not to be a little intrusive +% here. +% +% \begin{enumerate} +% \item Caption functionality which receives \meta{label} as optional +% argument, namely: +% \begin{enumerate} +% \item The \env{sidecaption} and \env{sidecontcaption} environments. These +% environments \emph{store} the label in an internal macro, +% \cs{m@mscaplabel}, at the begin environment code (more precisely in +% \cs[replace=false]{@@sidecaption}), but both the call to +% \cs{refstepcounter} and the expansion of \cs{m@mscaplabel} take place at +% \cs{endsidecaption}. For this reason, hooks are not particularly +% helpful, and there is not any easy way to grab the \meta{label} argument +% to start with. I can see two ways to deal with these environments, none +% of which I really like. First, map through \cs{m@mscaplabel} until +% \cs{label} is found, then grab the next token which is the \meta{label}. +% This can be used to set a \cs{zlabel} either with a kernel environment +% hook, or with \cs{@mem@scap@afterhook} (the former requires running +% \cs{refstepcounter} on our own, since the \texttt{env/.../end} hook +% comes before this is done by \cs{endsidecaption}). Second, locally +% redefine \cs{label} to set both labels inside the environments. +% \item The bilingual caption commands: \cs{bitwonumcaption}, +% \cs{bionenumcaption}, and \cs{bicaption}. These commands do not support +% setting the label in their arguments (the labels do get set, but they +% end up included in the \texttt{title} property of the label too). So we +% do the same for them as for \env{sidecaption}, just taking care of +% grouping, since we can't count on the convenience of the environment +% hook (luckily for us, they are scoped themselves, so we can add an extra +% group there). +% \end{enumerate} +% \item The \cs{subcaptionref} command, which makes a reference to the +% subcaption without the number of the main caption (e.g. ``(b)'', instead +% of ``2.3(b)''), for labels set inside the \meta{subtitle} argument of the +% subcaptioning commands, namely: \cs{subcaption}, \cs{contsubcaption}, +% \cs{subbottom}, \cs{contsubbottom}, \cs{subtop}. This functionality is +% implemented by \cls{memoir} by setting a \emph{second label} with prefix +% \texttt{sub@\meta{label}}, and storing there just that part of interest. +% With \pkg{zref} this part is easier, since we can just add an extra +% property and retrieve it later on. The thing is that it is hard to find a +% place to hook into to add the property to the \texttt{main} list, since +% \cls{memoir} does not really consider the possibility of some other +% command setting labels. \cs{@memsubcaption} is the best place to hook I +% could find. It is used by subcaptioning commands, and only those. And +% there is no hope for an environment hook in this case anyway. +% \item \cls{memoir}'s \cs{footnote}, \cs{verbfootnote}, \cs{sidefootnote} and +% \cs{pagenote}, just as the regular \cs{footnote} until recently in the +% kernel, do not set \cs{@currentcounter} alongside \cs{@currentlabel}, +% proper referencing to them requires setting the type for it. +% \item Note that \cls{memoir}'s appendix features ``emulates'' the +% \pkg{appendix} package, hence the corresponding compatibility module is +% loaded for \cls{memoir} even if that package is not itself loaded. The +% same is true for the \cs{appendix} command module, since it is also +% defined. +% \end{enumerate} +% +% +% \begin{macrocode} +\@@_compat_module:nn { memoir } + { + \@@_if_class_loaded:nT { memoir } + { +% \end{macrocode} +% Add subfigure and subtable support out of the box. Technically, this is not +% ``default'' behavior for \cls{memoir}, users have to enable it with +% \cs{newsubfloat}, but let this be smooth. Still, this does not cover any +% other floats created with \cs{newfloat}. Also include setup for +% \env{verse}. +% \begin{macrocode} + \@@_zcsetup:n + { + countertype = + { + subfigure = figure , + subtable = table , + poemline = line , + } , + counterresetby = + { + subfigure = figure , + subtable = table , + } , + } +% \end{macrocode} +% Support for caption \cls{memoir} features that require that \meta{label} be +% supplied as an optional argument. +% \begin{macrocode} + \cs_new_protected:Npn \@@_memoir_both_labels: + { + \cs_set_eq:NN \@@_memoir_orig_label:n \label + \cs_set:Npn \@@_memoir_label_and_zlabel:n ##1 + { + \@@_memoir_orig_label:n {##1} + \zlabel{##1} + } + \cs_set_eq:NN \label \@@_memoir_label_and_zlabel:n + } + \AddToHook { env / sidecaption / begin } + { \@@_memoir_both_labels: } + \AddToHook { env / sidecontcaption / begin } + { \@@_memoir_both_labels: } + \AddToHook{ cmd / bitwonumcaption / before } + { \group_begin: \@@_memoir_both_labels: } + \AddToHook{ cmd / bitwonumcaption / after } + { \group_end: } + \AddToHook{ cmd / bionenumcaption / before } + { \group_begin: \@@_memoir_both_labels: } + \AddToHook{ cmd / bionenumcaption / after } + { \group_end: } + \AddToHook{ cmd / bicaption / before } + { \group_begin: \@@_memoir_both_labels: } + \AddToHook{ cmd / bicaption / after } + { \group_end: } +% \end{macrocode} +% Support for \texttt{subcaption} reference. +% \begin{macrocode} + \zref@newprop { subcaption } + { \cs_if_exist_use:c { @@@@thesub \@captype } } + \AddToHook{ cmd / @memsubcaption / before } + { \zref@localaddprop \ZREF@mainlist { subcaption } } +% \end{macrocode} +% Support for \cs{footnote}, \cs{verbfootnote}, \cs{sidefootnote}, and +% \cs{pagenote}. +% \begin{macrocode} + \tl_new:N \l_@@_memoir_footnote_type_tl + \tl_set:Nn \l_@@_memoir_footnote_type_tl { footnote } + \AddToHook { env / minipage / begin } + { \tl_set:Nn \l_@@_memoir_footnote_type_tl { mpfootnote } } + \AddToHook { cmd / @makefntext / before } + { + \@@_zcsetup:x + { currentcounter = \l_@@_memoir_footnote_type_tl } + } + \AddToHook { cmd / @makesidefntext / before } + { \@@_zcsetup:n { currentcounter = sidefootnote } } + \@@_zcsetup:n + { + countertype = + { + sidefootnote = footnote , + pagenote = endnote , + } , + } + \AddToHook { file / \jobname.ent / before } + { \@@_zcsetup:x { currentcounter = pagenote } } + \msg_info:nnn { zref-clever } { compat-class } { memoir } + } + } +% \end{macrocode} +% +% +% +% \subsection{\opt{KOMA}} +% +% Support for \texttt{KOMA-Script} document classes. +% +% \begin{macrocode} +\@@_compat_module:nn { KOMA } + { + \cs_if_exist:NT \KOMAClassName + { +% \end{macrocode} +% Add support for \env{captionbeside} and \env{captionofbeside} environments. +% These environments \emph{do} run some variation of \cs{caption} and hence +% \cs{refstepcounter}. However, this happens inside a parbox inside the +% environment, thus grouped, such that we cannot see the variables set by +% \cs{refstepcounter} when we are setting the label. \cs{@currentlabel} is +% smuggled out of the group by KOMA, but the same care is not granted for +% \cs{@currentcounter}. So we have to rely on \cs{@captype}, which the +% underlying caption infrastructure feeds to \cs{refstepcounter}. Since we +% must use \texttt{env/.../after} hooks, care should be taken not to set the +% \opt{currentcounter} option unscoped, which would be quite disastrous. For +% this reason, though more ``invasive'', we set \cs{@currentcounter} instead, +% which at least will be set straight the next time \cs{refstepcounter} runs. +% It sounds reasonable, it is the same treatment \cs{@currentlabel} is +% receiving in this case. +% \begin{macrocode} + \AddToHook { env / captionbeside / after } + { + \tl_if_exist:NT \@captype + { \tl_set_eq:NN \@currentcounter \@captype } + } + \tl_new:N \g_@@_koma_captionofbeside_captype_tl + \AddToHook { env / captionofbeside / end } + { \tl_gset_eq:NN \g_@@_koma_captype_tl \@captype } + \AddToHook { env / captionofbeside / after } + { + \tl_if_eq:NnF \@currenvir { document } + { + \tl_if_empty:NF \g_@@_koma_captype_tl + { + \tl_set_eq:NN + \@currentcounter \g_@@_koma_captype_tl + } + } + \tl_gclear:N \g_@@_koma_captype_tl + } + \msg_info:nnx { zref-clever } { compat-class } { \KOMAClassName } + } + } +% \end{macrocode} +% +% +% +% \subsection{\opt{amsmath}} +% +% About this, see \url{https://tex.stackexchange.com/a/402297}. +% +% \begin{macrocode} +\@@_compat_module:nn { amsmath } + { + \@@_if_package_loaded:nT { amsmath } + { +% \end{macrocode} +% First, we define a function for label setting inside \pkg{amsmath} math +% environments, we want it to set both \cs{zlabel} and \cs{label}. We may +% ``get a ride'', but not steal the place altogether. This makes for +% potentially redundant labels, but seems a good compromise. We \emph{must} +% use the lower level \cs{zref@label} in this context, and hence also handle +% protection with \cs{zref@wrapper@babel}, because \cs{zlabel} makes itself +% no-op when \cs{label} is equal to \cs{ltx@gobble}, and that's precisely the +% case inside the \env{multline} environment (and, damn!, I took a beating of +% this detail\dots{}). +% \begin{macrocode} + \cs_set_nopar:Npn \@@_ltxlabel:n #1 + { + \@@_orig_ltxlabel:n {#1} + \zref@wrapper@babel \zref@label {#1} + } +% \end{macrocode} +% Then we must store the original value of \cs{ltx@label}, which is the macro +% actually responsible for setting the labels inside \pkg{amsmath}'s math +% environments. And, after that, redefine it to be \cs{@@_ltxlabel:n} +% instead. We must handle \pkg{hyperref} here, which comes very late in the +% preamble, and which loads \pkg{nameref} at \texttt{begindocument}, which in +% turn, lets \cs{ltx@label} be \cs{label}. This has to come after +% \pkg{nameref}. Other classes packages also redefine \cs{ltx@label}, which +% may cause some trouble. A \texttt{grep} on \texttt{texmf-dist} returns hits +% for: \file{thm-restate.sty}, \file{smartref.sty}, \file{jmlrbook.cls}, +% \file{cleveref.sty}, \file{cryptocode.sty}, \file{nameref.sty}, +% \file{easyeqn.sty}, \file{empheq.sty}, \file{ntheorem.sty}, +% \file{nccmath.sty}, \file{nwejm.cls}, \file{nwejmart.cls}, +% \file{aguplus.sty}, \file{aguplus.cls}, \file{agupp.sty}, +% \file{amsmath.hyp}, \file{amsmath.sty} (surprise!), \file{amsmath.4ht}, +% \file{nameref.4ht}, \file{frenchle.sty}, \file{french.sty}, plus +% corresponding documentations and different versions of the same packages. +% That's not too many, but not ``just a few'' either. The critical ones are +% explicitly handled here (\pkg{amsmath} itself, and \pkg{nameref}). A number +% of those I'm really not acquainted with. For \pkg{cleveref}, in particular, +% this procedure is not compatible with it. If we happen to come later than +% it and override its definition, this may be a substantial problem for +% \pkg{cleveref}, since it will find the label, but it won't contain the data +% it is expecting. However, this should normally not occur, if the user has +% followed the documented recommendation for \pkg{cleveref} to load it last, +% or at least very late, and besides I don't see much of an use case for using +% both \pkg{cleveref} and \pkg{zref-clever} together. I have documented in +% the user manual that this module may cause potential issues, and how to work +% around them. And I have made an upstream feature request for a hook, so +% that this could be made more cleanly at +% \url{https://github.com/latex3/hyperref/issues/212}. +% \begin{macrocode} + \@@_if_package_loaded:nTF { hyperref } + { + \AddToHook { package / nameref / after } + { + \cs_new_eq:NN \@@_orig_ltxlabel:n \ltx@label + \cs_set_eq:NN \ltx@label \@@_ltxlabel:n + } + } + { + \cs_new_eq:NN \@@_orig_ltxlabel:n \ltx@label + \cs_set_eq:NN \ltx@label \@@_ltxlabel:n + } +% \end{macrocode} +% The \env{subequations} environment uses \texttt{parentequation} and +% \texttt{equation} as counters, but only the later is subject to +% \cs{refstepcounter}. What happens is: at the start, \texttt{equation} is +% refstepped, it is then stored in \texttt{parentequation} and set to `0' and, +% at the end of the environment it is restored to the value of +% \texttt{parentequation}. We cannot even set \cs{@currentcounter} at +% \texttt{env/.../begin}, since the call to +% \cs{refstepcounter}\texttt{\{equation\}} done by \env{subequations} will +% override that in sequence. Unfortunately, the suggestion to set +% \cs{@currentcounter} to \texttt{parentequation} here was not accepted, see +% \url{https://github.com/latex3/latex2e/issues/687#issuecomment-951451024} +% and subsequent discussion. So, for \env{subequations}, we really must +% specify manually \opt{currentcounter} and the resetting. Note that, for +% \env{subequations}, \cs{zlabel} works just fine (that is, if given +% immediately after \texttt{\\begin\{subequations\}}, to refer to the +% parent equation). +% \begin{macrocode} + \AddToHook { env / subequations / begin } + { + \@@_zcsetup:x + { + counterresetby = + { + parentequation = + \@@_counter_reset_by:n { equation } , + equation = parentequation , + } , + currentcounter = parentequation , + countertype = { parentequation = equation } , + } + } +% \end{macrocode} +% \pkg{amsmath} does use \cs{refstepcounter} for the \texttt{equation} counter +% throughout and does set \cs{@currentcounter} for \cs{tag}s. But we still +% have to manually reset \opt{currentcounter} to default because, since we had +% to manually set \opt{currentcounter} to \texttt{parentequation} in +% \env{subequations}, we also have to manually set it to \env{equation} in +% environments which may be used within it. The \env{xxalignat} environment +% is not included, because it is ``starred'' by default (i.e.\ unnumbered), +% and does not display or accepts labels or tags anyway. The \env{-ed} +% (\env{gathered}, \env{aligned}, and \env{alignedat}) and \env{cases} +% environments ``must appear within an enclosing math environment''. Same +% logic applies to other environments defined or redefined by the package, +% like \env{array}, \env{matrix} and variations. Finally, \env{split} too can +% only be used as part of another environment. +% \begin{macrocode} + \clist_map_inline:nn + { + equation , + equation* , + align , + align* , + alignat , + alignat* , + flalign , + flalign* , + xalignat , + xalignat* , + gather , + gather* , + multline , + multline* , + } + { + \AddToHook { env / #1 / begin } + { \@@_zcsetup:n { currentcounter = equation } } + } +% \end{macrocode} +% And a last touch of care for \pkg{amsmath}'s refinements: make the equation +% references \cs{textup}. +% \begin{macrocode} + \zcRefTypeSetup { equation } + { + reffont = \upshape , + refpre = {\textup{(}} , + refpos = {\textup{)}} , + } + \msg_info:nnn { zref-clever } { compat-package } { amsmath } + } + } +% \end{macrocode} +% +% +% +% \subsection{\opt{mathtools}} +% +% All math environments defined by \pkg{mathtools}, extending the +% \pkg{amsmath} set, are meant to be used within enclosing math environments, +% hence we don't need to handle them specially, since the numbering and the +% counting is being done on the side of \pkg{amsmath}. This includes the new +% \env{cases} and \env{matrix} variants, and also \env{multlined}. +% +% Hence, as far as I can tell, the only cross-reference related feature to +% deal with is the \opt{showonlyrefs} option, whose machinery involves writing +% an extra internal label to the \file{.aux} file to track for labels which +% get actually referred to. This is a little more involved, and implies in +% doing special handling inside \cs{zcref}, but the feature is very cool, so +% it's worth it. +% +% \begin{macrocode} +\bool_new:N \l_@@_mathtools_showonlyrefs_bool +\@@_compat_module:nn { mathtools } + { + \@@_if_package_loaded:nT { mathtools } + { + \MH_if_boolean:nT { show_only_refs } + { + \bool_set_true:N \l_@@_mathtools_showonlyrefs_bool + \cs_new_protected:Npn \@@_mathtools_showonlyrefs:n #1 + { + \@bsphack + \seq_map_inline:Nn #1 + { + \exp_args:Nx \tl_if_eq:nnTF + { \@@_extract_unexp:nnn {##1} { zc@type } { } } + { equation } + { + \protected@write \@auxout { } + { \string \MT@newlabel {##1} } + } + { + \exp_args:Nx \tl_if_eq:nnT + { \@@_extract_unexp:nnn {##1} { zc@type } { } } + { parentequation } + { + \protected@write \@auxout { } + { \string \MT@newlabel {##1} } + } + } + } + \@esphack + } + \msg_info:nnn { zref-clever } { compat-package } { mathtools } + } + } + } +% \end{macrocode} +% +% +% \subsection{\opt{breqn}} +% +% From the \pkg{breqn} documentation: \textquote{Use of the normal \cs{label} +% command instead of the \opt{label} option works, I think, most of the time +% (untested)}. Indeed, light testing suggests it does work for \cs{zlabel} +% just as well. However, if it happens not to work, there was no easy +% alternative handle I could find. In particular, it does not seem viable to +% leverage the \opt{label=} option without hacking the package internals, even +% if the case of doing so would not be specially tricky, just ``not very +% civil''. +% +% \begin{macrocode} +\@@_compat_module:nn { breqn } + { + \@@_if_package_loaded:nT { breqn } + { +% \end{macrocode} +% Contrary to the practice in \pkg{amsmath}, which prints \cs{tag} even in +% unnumbered environments, the starred environments from \pkg{breqn} don't +% typeset any tag/number at all, even for a manually given \opt{number=} as an +% option. So, even if one can actually set a label in them, it is not really +% meaningful to make a reference to them. Also contrary to \pkg{amsmath}'s +% practice, \pkg{breqn} uses \cs{stepcounter} instead of \cs{refstepcounter} +% for incrementing the equation counters (see +% \url{https://tex.stackexchange.com/a/241150}). +% \begin{macrocode} + \AddToHook { env / dgroup / begin } + { + \@@_zcsetup:x + { + counterresetby = + { + parentequation = + \@@_counter_reset_by:n { equation } , + equation = parentequation , + } , + currentcounter = parentequation , + countertype = { parentequation = equation } , + } + } + \clist_map_inline:nn + { + dmath , + dseries , + darray , + } + { + \AddToHook { env / #1 / begin } + { \@@_zcsetup:n { currentcounter = equation } } + } + \msg_info:nnn { zref-clever } { compat-package } { breqn } + } + } +% \end{macrocode} +% +% +% +% \subsection{\opt{listings}} +% +% \begin{macrocode} +\@@_compat_module:nn { listings } + { + \@@_if_package_loaded:nT { listings } + { + \@@_zcsetup:n + { + countertype = + { + lstlisting = listing , + lstnumber = line , + } , + counterresetby = { lstnumber = lstlisting } , + } +% \end{macrocode} +% Set (also) a \cs{zlabel} with the label received in the \texttt{label=} +% option from the \texttt{lstlisting} environment. The \emph{only} place to +% set this label is the \texttt{PreInit} hook. This hook, comes right after +% \cs{lst@MakeCaption} in \cs{lst@Init}, which runs \cs{refstepcounter} on +% \texttt{lstlisting}, so we must come after it. Also \pkg{listings} itself +% sets \cs{@currentlabel} to \cs{thelstnumber} in the \texttt{Init} hook, +% which comes right after the \texttt{PreInit} one in \cs{lst@Init}. Since, +% if we add to \texttt{Init} here, we go to the end of it, we'd be seeing the +% wrong \cs{@currentlabel} at that point. +% \begin{macrocode} + \lst@AddToHook { PreInit } + { \tl_if_empty:NF \lst@label { \zlabel { \lst@label } } } +% \end{macrocode} +% Set \texttt{currentcounter} to \texttt{lstnumber} in the \texttt{Init} hook, +% since \pkg{listings} itself sets \cs{@currentlabel} to \cs{thelstnumber} +% here. Note that \pkg{listings} \emph{does use} \cs{refstepcounter} on +% \texttt{lstnumber}, but does so in the \texttt{EveryPar} hook, and there +% must be some grouping involved such that \cs{@currentcounter} ends up not +% being visible to the label. See section ``Line numbers'' of `\texttt{texdoc +% listings-devel}' (the \file{.dtx}), and search for the definition of macro +% \cs{c@lstnumber}. Indeed, the fact that \pkg{listings} manually sets +% \cs{@currentlabel} to \cs{thelstnumber} is a signal that the work of +% \cs{refstepcounter} is being restrained somehow. +% \begin{macrocode} + \lst@AddToHook { Init } + { \@@_zcsetup:n { currentcounter = lstnumber } } + \msg_info:nnn { zref-clever } { compat-package } { listings } + } + } +% \end{macrocode} +% +% +% \subsection{\opt{enumitem}} +% +% The procedure below will ``see'' any changes made to the \texttt{enumerate} +% environment (made with \pkg{enumitem}'s \cs{renewlist}) as long as it is +% done in the preamble. Though, technically, \cs{renewlist} can be issued +% anywhere in the document, this should be more than enough for the purpose at +% hand. Besides, trying to retrieve this information ``on the fly'' would be +% much overkill. +% +% The only real reason to ``renew'' \texttt{enumerate} itself is to change +% \marg{max-depth}. \cs{renewlist} \emph{hard-codes} \texttt{max-depth} in +% the environment's definition (well, just as the kernel does), so we cannot +% retrieve this information from any sort of variable. But \cs{renewlist} +% also creates any needed missing counters, so we can use their existence to +% make the appropriate settings. In the end, the existence of the counters is +% indeed what matters from \pkg{zref-clever}'s perspective. Since the first +% four are defined by the kernel and already setup for \pkg{zref-clever} by +% default, we start from \(5\), and stop at the first non-existent +% \cs[no-index]{c@enumN} counter. +% +% \begin{macrocode} +\@@_compat_module:nn { enumitem } + { + \@@_if_package_loaded:nT { enumitem } + { + \int_set:Nn \l_tmpa_int { 5 } + \bool_while_do:nn + { + \cs_if_exist_p:c + { c@ enum \int_to_roman:n { \l_tmpa_int } } + } + { + \@@_zcsetup:x + { + counterresetby = + { + enum \int_to_roman:n { \l_tmpa_int } = + enum \int_to_roman:n { \l_tmpa_int - 1 } + } , + countertype = + { enum \int_to_roman:n { \l_tmpa_int } = item } , + } + \int_incr:N \l_tmpa_int + } + \int_compare:nNnT { \l_tmpa_int } > { 5 } + { \msg_info:nnn { zref-clever } { compat-package } { enumitem } } + } + } +% \end{macrocode} +% +% +% +% \subsection{\opt{subcaption}} +% +% +% \begin{macrocode} +\@@_compat_module:nn { subcaption } + { + \@@_if_package_loaded:nT { subcaption } + { + \@@_zcsetup:n + { + countertype = + { + subfigure = figure , + subtable = table , + } , + counterresetby = + { + subfigure = figure , + subtable = table , + } , + } +% \end{macrocode} +% Support for \texttt{subref} reference. +% \begin{macrocode} + \zref@newprop { subref } + { \cs_if_exist_use:c { thesub \@captype } } + \tl_put_right:Nn \caption@subtypehook + { \zref@localaddprop \ZREF@mainlist { subref } } + } + } +% \end{macrocode} +% +% +% \subsection{\opt{subfig}} +% +% Though \pkg{subfig} offers \cs{subref} (as \pkg{subcaption}), I could not +% find any reasonable place to add the \texttt{subref} property to +% \pkg{zref}'s main list. +% +% \begin{macrocode} +\@@_compat_module:nn { subfig } + { + \@@_if_package_loaded:nT { subfig } + { + \@@_zcsetup:n + { + countertype = + { + subfigure = figure , + subtable = table , + } , + counterresetby = + { + subfigure = figure , + subtable = table , + } , + } + } + } +% \end{macrocode} +% +% +% \begin{macrocode} +% +% \end{macrocode} +% +% +% +% \section{Dictionaries} +% +% \subsection{English} +% +% \begin{macrocode} +%<*package> +\zcDeclareLanguage { english } +\zcDeclareLanguageAlias { american } { english } +\zcDeclareLanguageAlias { australian } { english } +\zcDeclareLanguageAlias { british } { english } +\zcDeclareLanguageAlias { canadian } { english } +\zcDeclareLanguageAlias { newzealand } { english } +\zcDeclareLanguageAlias { UKenglish } { english } +\zcDeclareLanguageAlias { USenglish } { english } +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dict-english> +% \end{macrocode} +% +% \begin{macrocode} +namesep = {\nobreakspace} , +pairsep = {~and\nobreakspace} , +listsep = {,~} , +lastsep = {~and\nobreakspace} , +tpairsep = {~and\nobreakspace} , +tlistsep = {,~} , +tlastsep = {,~and\nobreakspace} , +notesep = {~} , +rangesep = {~to\nobreakspace} , + +type = book , + Name-sg = Book , + name-sg = book , + Name-pl = Books , + name-pl = books , + +type = part , + Name-sg = Part , + name-sg = part , + Name-pl = Parts , + name-pl = parts , + +type = chapter , + Name-sg = Chapter , + name-sg = chapter , + Name-pl = Chapters , + name-pl = chapters , + +type = section , + Name-sg = Section , + name-sg = section , + Name-pl = Sections , + name-pl = sections , + +type = paragraph , + Name-sg = Paragraph , + name-sg = paragraph , + Name-pl = Paragraphs , + name-pl = paragraphs , + Name-sg-ab = Par. , + name-sg-ab = par. , + Name-pl-ab = Par. , + name-pl-ab = par. , + +type = appendix , + Name-sg = Appendix , + name-sg = appendix , + Name-pl = Appendices , + name-pl = appendices , + +type = subappendix , + Name-sg = Appendix , + name-sg = appendix , + Name-pl = Appendices , + name-pl = appendices , + +type = page , + Name-sg = Page , + name-sg = page , + Name-pl = Pages , + name-pl = pages , + name-sg-ab = p. , + name-pl-ab = pp. , + rangesep = {\textendash} , + +type = line , + Name-sg = Line , + name-sg = line , + Name-pl = Lines , + name-pl = lines , + +type = figure , + Name-sg = Figure , + name-sg = figure , + Name-pl = Figures , + name-pl = figures , + Name-sg-ab = Fig. , + name-sg-ab = fig. , + Name-pl-ab = Figs. , + name-pl-ab = figs. , + +type = table , + Name-sg = Table , + name-sg = table , + Name-pl = Tables , + name-pl = tables , + +type = item , + Name-sg = Item , + name-sg = item , + Name-pl = Items , + name-pl = items , + +type = footnote , + Name-sg = Footnote , + name-sg = footnote , + Name-pl = Footnotes , + name-pl = footnotes , + +type = endnote , + Name-sg = Note , + name-sg = note , + Name-pl = Notes , + name-pl = notes , + +type = note , + Name-sg = Note , + name-sg = note , + Name-pl = Notes , + name-pl = notes , + +type = equation , + Name-sg = Equation , + name-sg = equation , + Name-pl = Equations , + name-pl = equations , + Name-sg-ab = Eq. , + name-sg-ab = eq. , + Name-pl-ab = Eqs. , + name-pl-ab = eqs. , + refpre = {(} , + refpos = {)} , + +type = theorem , + Name-sg = Theorem , + name-sg = theorem , + Name-pl = Theorems , + name-pl = theorems , + +type = lemma , + Name-sg = Lemma , + name-sg = lemma , + Name-pl = Lemmas , + name-pl = lemmas , + +type = corollary , + Name-sg = Corollary , + name-sg = corollary , + Name-pl = Corollaries , + name-pl = corollaries , + +type = proposition , + Name-sg = Proposition , + name-sg = proposition , + Name-pl = Propositions , + name-pl = propositions , + +type = definition , + Name-sg = Definition , + name-sg = definition , + Name-pl = Definitions , + name-pl = definitions , + +type = proof , + Name-sg = Proof , + name-sg = proof , + Name-pl = Proofs , + name-pl = proofs , + +type = result , + Name-sg = Result , + name-sg = result , + Name-pl = Results , + name-pl = results , + +type = remark , + Name-sg = Remark , + name-sg = remark , + Name-pl = Remarks , + name-pl = remarks , + +type = example , + Name-sg = Example , + name-sg = example , + Name-pl = Examples , + name-pl = examples , + +type = algorithm , + Name-sg = Algorithm , + name-sg = algorithm , + Name-pl = Algorithms , + name-pl = algorithms , + +type = listing , + Name-sg = Listing , + name-sg = listing , + Name-pl = Listings , + name-pl = listings , + +type = exercise , + Name-sg = Exercise , + name-sg = exercise , + Name-pl = Exercises , + name-pl = exercises , + +type = solution , + Name-sg = Solution , + name-sg = solution , + Name-pl = Solutions , + name-pl = solutions , +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% +% +% \subsection{German} +% +% \begin{macrocode} +%<*package> +\zcDeclareLanguage + [ declension = { N , A , D , G } , gender = { f , m , n } , allcaps ] + { german } +\zcDeclareLanguageAlias { austrian } { german } +\zcDeclareLanguageAlias { germanb } { german } +\zcDeclareLanguageAlias { ngerman } { german } +\zcDeclareLanguageAlias { naustrian } { german } +\zcDeclareLanguageAlias { nswissgerman } { german } +\zcDeclareLanguageAlias { swissgerman } { german } +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dict-german> +% \end{macrocode} +% +% \begin{macrocode} +namesep = {\nobreakspace} , +pairsep = {~und\nobreakspace} , +listsep = {,~} , +lastsep = {~und\nobreakspace} , +tpairsep = {~und\nobreakspace} , +tlistsep = {,~} , +tlastsep = {~und\nobreakspace} , +notesep = {~} , +rangesep = {~bis\nobreakspace} , + +type = book , + gender = n , + case = N , + Name-sg = Buch , + Name-pl = Bücher , + case = A , + Name-sg = Buch , + Name-pl = Bücher , + case = D , + Name-sg = Buch , + Name-pl = Büchern , + case = G , + Name-sg = Buches , + Name-pl = Bücher , + +type = part , + gender = m , + case = N , + Name-sg = Teil , + Name-pl = Teile , + case = A , + Name-sg = Teil , + Name-pl = Teile , + case = D , + Name-sg = Teil , + Name-pl = Teilen , + case = G , + Name-sg = Teiles , + Name-pl = Teile , + +type = chapter , + gender = n , + case = N , + Name-sg = Kapitel , + Name-pl = Kapitel , + case = A , + Name-sg = Kapitel , + Name-pl = Kapitel , + case = D , + Name-sg = Kapitel , + Name-pl = Kapiteln , + case = G , + Name-sg = Kapitels , + Name-pl = Kapitel , + +type = section , + gender = m , + case = N , + Name-sg = Abschnitt , + Name-pl = Abschnitte , + case = A , + Name-sg = Abschnitt , + Name-pl = Abschnitte , + case = D , + Name-sg = Abschnitt , + Name-pl = Abschnitten , + case = G , + Name-sg = Abschnitts , + Name-pl = Abschnitte , + +type = paragraph , + gender = m , + case = N , + Name-sg = Absatz , + Name-pl = Absätze , + case = A , + Name-sg = Absatz , + Name-pl = Absätze , + case = D , + Name-sg = Absatz , + Name-pl = Absätzen , + case = G , + Name-sg = Absatzes , + Name-pl = Absätze , + +type = appendix , + gender = m , + case = N , + Name-sg = Anhang , + Name-pl = Anhänge , + case = A , + Name-sg = Anhang , + Name-pl = Anhänge , + case = D , + Name-sg = Anhang , + Name-pl = Anhängen , + case = G , + Name-sg = Anhangs , + Name-pl = Anhänge , + +type = subappendix , + gender = m , + case = N , + Name-sg = Anhang , + Name-pl = Anhänge , + case = A , + Name-sg = Anhang , + Name-pl = Anhänge , + case = D , + Name-sg = Anhang , + Name-pl = Anhängen , + case = G , + Name-sg = Anhangs , + Name-pl = Anhänge , + +type = page , + gender = f , + case = N , + Name-sg = Seite , + Name-pl = Seiten , + case = A , + Name-sg = Seite , + Name-pl = Seiten , + case = D , + Name-sg = Seite , + Name-pl = Seiten , + case = G , + Name-sg = Seite , + Name-pl = Seiten , + rangesep = {\textendash} , + +type = line , + gender = f , + case = N , + Name-sg = Zeile , + Name-pl = Zeilen , + case = A , + Name-sg = Zeile , + Name-pl = Zeilen , + case = D , + Name-sg = Zeile , + Name-pl = Zeilen , + case = G , + Name-sg = Zeile , + Name-pl = Zeilen , + +type = figure , + gender = f , + case = N , + Name-sg = Abbildung , + Name-pl = Abbildungen , + Name-sg-ab = Abb. , + Name-pl-ab = Abb. , + case = A , + Name-sg = Abbildung , + Name-pl = Abbildungen , + Name-sg-ab = Abb. , + Name-pl-ab = Abb. , + case = D , + Name-sg = Abbildung , + Name-pl = Abbildungen , + Name-sg-ab = Abb. , + Name-pl-ab = Abb. , + case = G , + Name-sg = Abbildung , + Name-pl = Abbildungen , + Name-sg-ab = Abb. , + Name-pl-ab = Abb. , + +type = table , + gender = f , + case = N , + Name-sg = Tabelle , + Name-pl = Tabellen , + case = A , + Name-sg = Tabelle , + Name-pl = Tabellen , + case = D , + Name-sg = Tabelle , + Name-pl = Tabellen , + case = G , + Name-sg = Tabelle , + Name-pl = Tabellen , + +type = item , + gender = m , + case = N , + Name-sg = Punkt , + Name-pl = Punkte , + case = A , + Name-sg = Punkt , + Name-pl = Punkte , + case = D , + Name-sg = Punkt , + Name-pl = Punkten , + case = G , + Name-sg = Punktes , + Name-pl = Punkte , + +type = footnote , + gender = f , + case = N , + Name-sg = Fußnote , + Name-pl = Fußnoten , + case = A , + Name-sg = Fußnote , + Name-pl = Fußnoten , + case = D , + Name-sg = Fußnote , + Name-pl = Fußnoten , + case = G , + Name-sg = Fußnote , + Name-pl = Fußnoten , + +type = endnote , + gender = f , + case = N , + Name-sg = Endnote , + Name-pl = Endnoten , + case = A , + Name-sg = Endnote , + Name-pl = Endnoten , + case = D , + Name-sg = Endnote , + Name-pl = Endnoten , + case = G , + Name-sg = Endnote , + Name-pl = Endnoten , + +type = note , + gender = f , + case = N , + Name-sg = Anmerkung , + Name-pl = Anmerkungen , + case = A , + Name-sg = Anmerkung , + Name-pl = Anmerkungen , + case = D , + Name-sg = Anmerkung , + Name-pl = Anmerkungen , + case = G , + Name-sg = Anmerkung , + Name-pl = Anmerkungen , + +type = equation , + gender = f , + case = N , + Name-sg = Gleichung , + Name-pl = Gleichungen , + case = A , + Name-sg = Gleichung , + Name-pl = Gleichungen , + case = D , + Name-sg = Gleichung , + Name-pl = Gleichungen , + case = G , + Name-sg = Gleichung , + Name-pl = Gleichungen , + refpre = {(} , + refpos = {)} , + +type = theorem , + gender = n , + case = N , + Name-sg = Theorem , + Name-pl = Theoreme , + case = A , + Name-sg = Theorem , + Name-pl = Theoreme , + case = D , + Name-sg = Theorem , + Name-pl = Theoremen , + case = G , + Name-sg = Theorems , + Name-pl = Theoreme , + +type = lemma , + gender = n , + case = N , + Name-sg = Lemma , + Name-pl = Lemmata , + case = A , + Name-sg = Lemma , + Name-pl = Lemmata , + case = D , + Name-sg = Lemma , + Name-pl = Lemmata , + case = G , + Name-sg = Lemmas , + Name-pl = Lemmata , + +type = corollary , + gender = n , + case = N , + Name-sg = Korollar , + Name-pl = Korollare , + case = A , + Name-sg = Korollar , + Name-pl = Korollare , + case = D , + Name-sg = Korollar , + Name-pl = Korollaren , + case = G , + Name-sg = Korollars , + Name-pl = Korollare , + +type = proposition , + gender = m , + case = N , + Name-sg = Satz , + Name-pl = Sätze , + case = A , + Name-sg = Satz , + Name-pl = Sätze , + case = D , + Name-sg = Satz , + Name-pl = Sätzen , + case = G , + Name-sg = Satzes , + Name-pl = Sätze , + +type = definition , + gender = f , + case = N , + Name-sg = Definition , + Name-pl = Definitionen , + case = A , + Name-sg = Definition , + Name-pl = Definitionen , + case = D , + Name-sg = Definition , + Name-pl = Definitionen , + case = G , + Name-sg = Definition , + Name-pl = Definitionen , + +type = proof , + gender = m , + case = N , + Name-sg = Beweis , + Name-pl = Beweise , + case = A , + Name-sg = Beweis , + Name-pl = Beweise , + case = D , + Name-sg = Beweis , + Name-pl = Beweisen , + case = G , + Name-sg = Beweises , + Name-pl = Beweise , + +type = result , + gender = n , + case = N , + Name-sg = Ergebnis , + Name-pl = Ergebnisse , + case = A , + Name-sg = Ergebnis , + Name-pl = Ergebnisse , + case = D , + Name-sg = Ergebnis , + Name-pl = Ergebnissen , + case = G , + Name-sg = Ergebnisses , + Name-pl = Ergebnisse , + +type = remark , + gender = f , + case = N , + Name-sg = Bemerkung , + Name-pl = Bemerkungen , + case = A , + Name-sg = Bemerkung , + Name-pl = Bemerkungen , + case = D , + Name-sg = Bemerkung , + Name-pl = Bemerkungen , + case = G , + Name-sg = Bemerkung , + Name-pl = Bemerkungen , + +type = example , + gender = n , + case = N , + Name-sg = Beispiel , + Name-pl = Beispiele , + case = A , + Name-sg = Beispiel , + Name-pl = Beispiele , + case = D , + Name-sg = Beispiel , + Name-pl = Beispielen , + case = G , + Name-sg = Beispiels , + Name-pl = Beispiele , + +type = algorithm , + gender = m , + case = N , + Name-sg = Algorithmus , + Name-pl = Algorithmen , + case = A , + Name-sg = Algorithmus , + Name-pl = Algorithmen , + case = D , + Name-sg = Algorithmus , + Name-pl = Algorithmen , + case = G , + Name-sg = Algorithmus , + Name-pl = Algorithmen , + +type = listing , + gender = n , + case = N , + Name-sg = Listing , + Name-pl = Listings , + case = A , + Name-sg = Listing , + Name-pl = Listings , + case = D , + Name-sg = Listing , + Name-pl = Listings , + case = G , + Name-sg = Listings , + Name-pl = Listings , + +type = exercise , + gender = f , + case = N , + Name-sg = Übungsaufgabe , + Name-pl = Übungsaufgaben , + case = A , + Name-sg = Übungsaufgabe , + Name-pl = Übungsaufgaben , + case = D , + Name-sg = Übungsaufgabe , + Name-pl = Übungsaufgaben , + case = G , + Name-sg = Übungsaufgabe , + Name-pl = Übungsaufgaben , + +type = solution , + gender = f , + case = N , + Name-sg = Lösung , + Name-pl = Lösungen , + case = A , + Name-sg = Lösung , + Name-pl = Lösungen , + case = D , + Name-sg = Lösung , + Name-pl = Lösungen , + case = G , + Name-sg = Lösung , + Name-pl = Lösungen , +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% +% +% \subsection{French} +% +% \begin{macrocode} +%<*package> +\zcDeclareLanguage [ gender = { f , m } ] { french } +\zcDeclareLanguageAlias { acadian } { french } +\zcDeclareLanguageAlias { canadien } { french } +\zcDeclareLanguageAlias { francais } { french } +\zcDeclareLanguageAlias { frenchb } { french } +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dict-french> +% \end{macrocode} +% +% \begin{macrocode} +namesep = {\nobreakspace} , +pairsep = {~et\nobreakspace} , +listsep = {,~} , +lastsep = {~et\nobreakspace} , +tpairsep = {~et\nobreakspace} , +tlistsep = {,~} , +tlastsep = {~et\nobreakspace} , +notesep = {~} , +rangesep = {~à\nobreakspace} , + +type = book , + gender = m , + Name-sg = Livre , + name-sg = livre , + Name-pl = Livres , + name-pl = livres , + +type = part , + gender = f , + Name-sg = Partie , + name-sg = partie , + Name-pl = Parties , + name-pl = parties , + +type = chapter , + gender = m , + Name-sg = Chapitre , + name-sg = chapitre , + Name-pl = Chapitres , + name-pl = chapitres , + +type = section , + gender = f , + Name-sg = Section , + name-sg = section , + Name-pl = Sections , + name-pl = sections , + +type = paragraph , + gender = m , + Name-sg = Paragraphe , + name-sg = paragraphe , + Name-pl = Paragraphes , + name-pl = paragraphes , + +type = appendix , + gender = f , + Name-sg = Annexe , + name-sg = annexe , + Name-pl = Annexes , + name-pl = annexes , + +type = subappendix , + gender = f , + Name-sg = Annexe , + name-sg = annexe , + Name-pl = Annexes , + name-pl = annexes , + +type = page , + gender = f , + Name-sg = Page , + name-sg = page , + Name-pl = Pages , + name-pl = pages , + rangesep = {\textendash} , + +type = line , + gender = f , + Name-sg = Ligne , + name-sg = ligne , + Name-pl = Lignes , + name-pl = lignes , + +type = figure , + gender = f , + Name-sg = Figure , + name-sg = figure , + Name-pl = Figures , + name-pl = figures , + +type = table , + gender = f , + Name-sg = Table , + name-sg = table , + Name-pl = Tables , + name-pl = tables , + +type = item , + gender = m , + Name-sg = Point , + name-sg = point , + Name-pl = Points , + name-pl = points , + +type = footnote , + gender = f , + Name-sg = Note , + name-sg = note , + Name-pl = Notes , + name-pl = notes , + +type = endnote , + gender = f , + Name-sg = Note , + name-sg = note , + Name-pl = Notes , + name-pl = notes , + +type = note , + gender = f , + Name-sg = Note , + name-sg = note , + Name-pl = Notes , + name-pl = notes , + +type = equation , + gender = f , + Name-sg = Équation , + name-sg = équation , + Name-pl = Équations , + name-pl = équations , + refpre = {(} , + refpos = {)} , + +type = theorem , + gender = m , + Name-sg = Théorème , + name-sg = théorème , + Name-pl = Théorèmes , + name-pl = théorèmes , + +type = lemma , + gender = m , + Name-sg = Lemme , + name-sg = lemme , + Name-pl = Lemmes , + name-pl = lemmes , + +type = corollary , + gender = m , + Name-sg = Corollaire , + name-sg = corollaire , + Name-pl = Corollaires , + name-pl = corollaires , + +type = proposition , + gender = f , + Name-sg = Proposition , + name-sg = proposition , + Name-pl = Propositions , + name-pl = propositions , + +type = definition , + gender = f , + Name-sg = Définition , + name-sg = définition , + Name-pl = Définitions , + name-pl = définitions , + +type = proof , + gender = f , + Name-sg = Démonstration , + name-sg = démonstration , + Name-pl = Démonstrations , + name-pl = démonstrations , + +type = result , + gender = m , + Name-sg = Résultat , + name-sg = résultat , + Name-pl = Résultats , + name-pl = résultats , + +type = remark , + gender = f , + Name-sg = Remarque , + name-sg = remarque , + Name-pl = Remarques , + name-pl = remarques , + +type = example , + gender = m , + Name-sg = Exemple , + name-sg = exemple , + Name-pl = Exemples , + name-pl = exemples , + +type = algorithm , + gender = m , + Name-sg = Algorithme , + name-sg = algorithme , + Name-pl = Algorithmes , + name-pl = algorithmes , + +type = listing , + gender = f , + Name-sg = Liste , + name-sg = liste , + Name-pl = Listes , + name-pl = listes , + +type = exercise , + gender = m , + Name-sg = Exercice , + name-sg = exercice , + Name-pl = Exercices , + name-pl = exercices , + +type = solution , + gender = f , + Name-sg = Solution , + name-sg = solution , + Name-pl = Solutions , + name-pl = solutions , +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% +% +% \subsection{Portuguese} +% +% \begin{macrocode} +%<*package> +\zcDeclareLanguage [ gender = { f , m } ] { portuguese } +\zcDeclareLanguageAlias { brazilian } { portuguese } +\zcDeclareLanguageAlias { brazil } { portuguese } +\zcDeclareLanguageAlias { portuges } { portuguese } +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dict-portuguese> +% \end{macrocode} +% +% \begin{macrocode} +namesep = {\nobreakspace} , +pairsep = {~e\nobreakspace} , +listsep = {,~} , +lastsep = {~e\nobreakspace} , +tpairsep = {~e\nobreakspace} , +tlistsep = {,~} , +tlastsep = {~e\nobreakspace} , +notesep = {~} , +rangesep = {~a\nobreakspace} , + +type = book , + gender = m , + Name-sg = Livro , + name-sg = livro , + Name-pl = Livros , + name-pl = livros , + +type = part , + gender = f , + Name-sg = Parte , + name-sg = parte , + Name-pl = Partes , + name-pl = partes , + +type = chapter , + gender = m , + Name-sg = Capítulo , + name-sg = capítulo , + Name-pl = Capítulos , + name-pl = capítulos , + +type = section , + gender = f , + Name-sg = Seção , + name-sg = seção , + Name-pl = Seções , + name-pl = seções , + +type = paragraph , + gender = m , + Name-sg = Parágrafo , + name-sg = parágrafo , + Name-pl = Parágrafos , + name-pl = parágrafos , + Name-sg-ab = Par. , + name-sg-ab = par. , + Name-pl-ab = Par. , + name-pl-ab = par. , + +type = appendix , + gender = m , + Name-sg = Apêndice , + name-sg = apêndice , + Name-pl = Apêndices , + name-pl = apêndices , + +type = subappendix , + gender = m , + Name-sg = Apêndice , + name-sg = apêndice , + Name-pl = Apêndices , + name-pl = apêndices , + +type = page , + gender = f , + Name-sg = Página , + name-sg = página , + Name-pl = Páginas , + name-pl = páginas , + name-sg-ab = p. , + name-pl-ab = pp. , + rangesep = {\textendash} , + +type = line , + gender = f , + Name-sg = Linha , + name-sg = linha , + Name-pl = Linhas , + name-pl = linhas , + +type = figure , + gender = f , + Name-sg = Figura , + name-sg = figura , + Name-pl = Figuras , + name-pl = figuras , + Name-sg-ab = Fig. , + name-sg-ab = fig. , + Name-pl-ab = Figs. , + name-pl-ab = figs. , + +type = table , + gender = f , + Name-sg = Tabela , + name-sg = tabela , + Name-pl = Tabelas , + name-pl = tabelas , + +type = item , + gender = m , + Name-sg = Item , + name-sg = item , + Name-pl = Itens , + name-pl = itens , + +type = footnote , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = endnote , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = note , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = equation , + gender = f , + Name-sg = Equação , + name-sg = equação , + Name-pl = Equações , + name-pl = equações , + Name-sg-ab = Eq. , + name-sg-ab = eq. , + Name-pl-ab = Eqs. , + name-pl-ab = eqs. , + refpre = {(} , + refpos = {)} , + +type = theorem , + gender = m , + Name-sg = Teorema , + name-sg = teorema , + Name-pl = Teoremas , + name-pl = teoremas , + +type = lemma , + gender = m , + Name-sg = Lema , + name-sg = lema , + Name-pl = Lemas , + name-pl = lemas , + +type = corollary , + gender = m , + Name-sg = Corolário , + name-sg = corolário , + Name-pl = Corolários , + name-pl = corolários , + +type = proposition , + gender = f , + Name-sg = Proposição , + name-sg = proposição , + Name-pl = Proposições , + name-pl = proposições , + +type = definition , + gender = f , + Name-sg = Definição , + name-sg = definição , + Name-pl = Definições , + name-pl = definições , + +type = proof , + gender = f , + Name-sg = Demonstração , + name-sg = demonstração , + Name-pl = Demonstrações , + name-pl = demonstrações , + +type = result , + gender = m , + Name-sg = Resultado , + name-sg = resultado , + Name-pl = Resultados , + name-pl = resultados , + +type = remark , + gender = f , + Name-sg = Observação , + name-sg = observação , + Name-pl = Observações , + name-pl = observações , + +type = example , + gender = m , + Name-sg = Exemplo , + name-sg = exemplo , + Name-pl = Exemplos , + name-pl = exemplos , + +type = algorithm , + gender = m , + Name-sg = Algoritmo , + name-sg = algoritmo , + Name-pl = Algoritmos , + name-pl = algoritmos , + +type = listing , + gender = f , + Name-sg = Listagem , + name-sg = listagem , + Name-pl = Listagens , + name-pl = listagens , + +type = exercise , + gender = m , + Name-sg = Exercício , + name-sg = exercício , + Name-pl = Exercícios , + name-pl = exercícios , + +type = solution , + gender = f , + Name-sg = Solução , + name-sg = solução , + Name-pl = Soluções , + name-pl = soluções , +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% +% +% \subsection{Spanish} +% +% \begin{macrocode} +%<*package> +\zcDeclareLanguage [ gender = { f , m } ] { spanish } +% +% \end{macrocode} +% +% \begin{macrocode} +%<*dict-spanish> +% \end{macrocode} +% +% \begin{macrocode} +namesep = {\nobreakspace} , +pairsep = {~y\nobreakspace} , +listsep = {,~} , +lastsep = {~y\nobreakspace} , +tpairsep = {~y\nobreakspace} , +tlistsep = {,~} , +tlastsep = {~y\nobreakspace} , +notesep = {~} , +rangesep = {~a\nobreakspace} , + +type = book , + gender = m , + Name-sg = Libro , + name-sg = libro , + Name-pl = Libros , + name-pl = libros , + +type = part , + gender = f , + Name-sg = Parte , + name-sg = parte , + Name-pl = Partes , + name-pl = partes , + +type = chapter , + gender = m , + Name-sg = Capítulo , + name-sg = capítulo , + Name-pl = Capítulos , + name-pl = capítulos , + +type = section , + gender = f , + Name-sg = Sección , + name-sg = sección , + Name-pl = Secciones , + name-pl = secciones , + +type = paragraph , + gender = m , + Name-sg = Párrafo , + name-sg = párrafo , + Name-pl = Párrafos , + name-pl = párrafos , + +type = appendix , + gender = m , + Name-sg = Apéndice , + name-sg = apéndice , + Name-pl = Apéndices , + name-pl = apéndices , + +type = subappendix , + gender = m , + Name-sg = Apéndice , + name-sg = apéndice , + Name-pl = Apéndices , + name-pl = apéndices , + +type = page , + gender = f , + Name-sg = Página , + name-sg = página , + Name-pl = Páginas , + name-pl = páginas , + rangesep = {\textendash} , + +type = line , + gender = f , + Name-sg = Línea , + name-sg = línea , + Name-pl = Líneas , + name-pl = líneas , + +type = figure , + gender = f , + Name-sg = Figura , + name-sg = figura , + Name-pl = Figuras , + name-pl = figuras , + +type = table , + gender = m , + Name-sg = Cuadro , + name-sg = cuadro , + Name-pl = Cuadros , + name-pl = cuadros , + +type = item , + gender = m , + Name-sg = Punto , + name-sg = punto , + Name-pl = Puntos , + name-pl = puntos , + +type = footnote , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = endnote , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = note , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = equation , + gender = f , + Name-sg = Ecuación , + name-sg = ecuación , + Name-pl = Ecuaciones , + name-pl = ecuaciones , + refpre = {(} , + refpos = {)} , + +type = theorem , + gender = m , + Name-sg = Teorema , + name-sg = teorema , + Name-pl = Teoremas , + name-pl = teoremas , + +type = lemma , + gender = m , + Name-sg = Lema , + name-sg = lema , + Name-pl = Lemas , + name-pl = lemas , + +type = corollary , + gender = m , + Name-sg = Corolario , + name-sg = corolario , + Name-pl = Corolarios , + name-pl = corolarios , + +type = proposition , + gender = f , + Name-sg = Proposición , + name-sg = proposición , + Name-pl = Proposiciones , + name-pl = proposiciones , + +type = definition , + gender = f , + Name-sg = Definición , + name-sg = definición , + Name-pl = Definiciones , + name-pl = definiciones , + +type = proof , + gender = f , + Name-sg = Demostración , + name-sg = demostración , + Name-pl = Demostraciones , + name-pl = demostraciones , + +type = result , + gender = m , + Name-sg = Resultado , + name-sg = resultado , + Name-pl = Resultados , + name-pl = resultados , + +type = remark , + gender = f , + Name-sg = Observación , + name-sg = observación , + Name-pl = Observaciones , + name-pl = observaciones , + +type = example , + gender = m , + Name-sg = Ejemplo , + name-sg = ejemplo , + Name-pl = Ejemplos , + name-pl = ejemplos , + +type = algorithm , + gender = m , + Name-sg = Algoritmo , + name-sg = algoritmo , + Name-pl = Algoritmos , + name-pl = algoritmos , + +type = listing , + gender = m , + Name-sg = Listado , + name-sg = listado , + Name-pl = Listados , + name-pl = listados , + +type = exercise , + gender = m , + Name-sg = Ejercicio , + name-sg = ejercicio , + Name-pl = Ejercicios , + name-pl = ejercicios , + +type = solution , + gender = f , + Name-sg = Solución , + name-sg = solución , + Name-pl = Soluciones , + name-pl = soluciones , +% \end{macrocode} +% +% \begin{macrocode} +% +% \end{macrocode} +% +% +% \PrintIndex +% +% diff --git a/Master/texmf-dist/source/latex/zref-clever/zref-clever.ins b/Master/texmf-dist/source/latex/zref-clever/zref-clever.ins new file mode 100644 index 00000000000..71259f4751f --- /dev/null +++ b/Master/texmf-dist/source/latex/zref-clever/zref-clever.ins @@ -0,0 +1,99 @@ +% \iffalse meta-comment +% +% File: zref-clever.ins +% +% This file is part of the LaTeX package "zref-clever". +% +% Copyright (C) 2021 Gustavo Barros +% +% It may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this +% license or (at your option) any later version. The latest version +% of this license is in the file: +% +% https://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 is "maintained" (as per LPPL maintenance status) by +% Gustavo Barros. +% +% This work consists of the files zref-clever.dtx, +% zref-clever.ins, +% zref-clever.tex, +% zref-clever-code.tex, +% and the derived files listed in MANIFEST.md. +% +% The released version of this package is available from CTAN. +% +% ----------------------------------------------------------------------- +% +% The development version of the package can be found at +% +% https://github.com/gusbrs/zref-clever +% +% for those people who are interested. +% +% ----------------------------------------------------------------------- +% +% \fi + +\input l3docstrip.tex + +\keepsilent + +\askforoverwritefalse + +\preamble + +This file was generated from file(s) of the LaTeX package "zref-clever". + +Copyright (C) 2021 Gustavo Barros + +It may be distributed and/or modified under the conditions of the +LaTeX Project Public License (LPPL), either version 1.3c of this +license or (at your option) any later version. The latest version +of this license is in the file: + + https://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 is "maintained" (as per LPPL maintenance status) by + Gustavo Barros. + +This work consists of the files zref-clever.dtx, + zref-clever.ins, + zref-clever.tex, + zref-clever-code.tex, +and the derived files listed in MANIFEST.md. + +The released version of this package is available from CTAN. + +----------------------------------------------------------------------- + +The development version of the package can be found at + + https://github.com/gusbrs/zref-clever + +for those people who are interested. + +----------------------------------------------------------------------- + +\endpreamble + +\postamble +\endpostamble + +\generate{\file{zref-clever.sty}{\from{zref-clever.dtx}{package}}} +\generate{\file{zref-clever-english.dict}{\from{zref-clever.dtx}{dict-english}}} +\generate{\file{zref-clever-german.dict}{\from{zref-clever.dtx}{dict-german}}} +\generate{\file{zref-clever-french.dict}{\from{zref-clever.dtx}{dict-french}}} +\generate{\file{zref-clever-portuguese.dict}{\from{zref-clever.dtx}{dict-portuguese}}} +\generate{\file{zref-clever-spanish.dict}{\from{zref-clever.dtx}{dict-spanish}}} + +\endbatchfile diff --git a/Master/texmf-dist/tex/latex/zref-clever/zref-clever-english.dict b/Master/texmf-dist/tex/latex/zref-clever/zref-clever-english.dict new file mode 100644 index 00000000000..2b7530e24ae --- /dev/null +++ b/Master/texmf-dist/tex/latex/zref-clever/zref-clever-english.dict @@ -0,0 +1,247 @@ +%% +%% This is file `zref-clever-english.dict', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% zref-clever.dtx (with options: `dict-english') +%% +%% This file was generated from file(s) of the LaTeX package "zref-clever". +%% +%% Copyright (C) 2021 Gustavo Barros +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file: +%% +%% https://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 is "maintained" (as per LPPL maintenance status) by +%% Gustavo Barros. +%% +%% This work consists of the files zref-clever.dtx, +%% zref-clever.ins, +%% zref-clever.tex, +%% zref-clever-code.tex, +%% and the derived files listed in MANIFEST.md. +%% +%% The released version of this package is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the package can be found at +%% +%% https://github.com/gusbrs/zref-clever +%% +%% for those people who are interested. +%% +%% ----------------------------------------------------------------------- +%% +namesep = {\nobreakspace} , +pairsep = {~and\nobreakspace} , +listsep = {,~} , +lastsep = {~and\nobreakspace} , +tpairsep = {~and\nobreakspace} , +tlistsep = {,~} , +tlastsep = {,~and\nobreakspace} , +notesep = {~} , +rangesep = {~to\nobreakspace} , + +type = book , + Name-sg = Book , + name-sg = book , + Name-pl = Books , + name-pl = books , + +type = part , + Name-sg = Part , + name-sg = part , + Name-pl = Parts , + name-pl = parts , + +type = chapter , + Name-sg = Chapter , + name-sg = chapter , + Name-pl = Chapters , + name-pl = chapters , + +type = section , + Name-sg = Section , + name-sg = section , + Name-pl = Sections , + name-pl = sections , + +type = paragraph , + Name-sg = Paragraph , + name-sg = paragraph , + Name-pl = Paragraphs , + name-pl = paragraphs , + Name-sg-ab = Par. , + name-sg-ab = par. , + Name-pl-ab = Par. , + name-pl-ab = par. , + +type = appendix , + Name-sg = Appendix , + name-sg = appendix , + Name-pl = Appendices , + name-pl = appendices , + +type = subappendix , + Name-sg = Appendix , + name-sg = appendix , + Name-pl = Appendices , + name-pl = appendices , + +type = page , + Name-sg = Page , + name-sg = page , + Name-pl = Pages , + name-pl = pages , + name-sg-ab = p. , + name-pl-ab = pp. , + rangesep = {\textendash} , + +type = line , + Name-sg = Line , + name-sg = line , + Name-pl = Lines , + name-pl = lines , + +type = figure , + Name-sg = Figure , + name-sg = figure , + Name-pl = Figures , + name-pl = figures , + Name-sg-ab = Fig. , + name-sg-ab = fig. , + Name-pl-ab = Figs. , + name-pl-ab = figs. , + +type = table , + Name-sg = Table , + name-sg = table , + Name-pl = Tables , + name-pl = tables , + +type = item , + Name-sg = Item , + name-sg = item , + Name-pl = Items , + name-pl = items , + +type = footnote , + Name-sg = Footnote , + name-sg = footnote , + Name-pl = Footnotes , + name-pl = footnotes , + +type = endnote , + Name-sg = Note , + name-sg = note , + Name-pl = Notes , + name-pl = notes , + +type = note , + Name-sg = Note , + name-sg = note , + Name-pl = Notes , + name-pl = notes , + +type = equation , + Name-sg = Equation , + name-sg = equation , + Name-pl = Equations , + name-pl = equations , + Name-sg-ab = Eq. , + name-sg-ab = eq. , + Name-pl-ab = Eqs. , + name-pl-ab = eqs. , + refpre = {(} , + refpos = {)} , + +type = theorem , + Name-sg = Theorem , + name-sg = theorem , + Name-pl = Theorems , + name-pl = theorems , + +type = lemma , + Name-sg = Lemma , + name-sg = lemma , + Name-pl = Lemmas , + name-pl = lemmas , + +type = corollary , + Name-sg = Corollary , + name-sg = corollary , + Name-pl = Corollaries , + name-pl = corollaries , + +type = proposition , + Name-sg = Proposition , + name-sg = proposition , + Name-pl = Propositions , + name-pl = propositions , + +type = definition , + Name-sg = Definition , + name-sg = definition , + Name-pl = Definitions , + name-pl = definitions , + +type = proof , + Name-sg = Proof , + name-sg = proof , + Name-pl = Proofs , + name-pl = proofs , + +type = result , + Name-sg = Result , + name-sg = result , + Name-pl = Results , + name-pl = results , + +type = remark , + Name-sg = Remark , + name-sg = remark , + Name-pl = Remarks , + name-pl = remarks , + +type = example , + Name-sg = Example , + name-sg = example , + Name-pl = Examples , + name-pl = examples , + +type = algorithm , + Name-sg = Algorithm , + name-sg = algorithm , + Name-pl = Algorithms , + name-pl = algorithms , + +type = listing , + Name-sg = Listing , + name-sg = listing , + Name-pl = Listings , + name-pl = listings , + +type = exercise , + Name-sg = Exercise , + name-sg = exercise , + Name-pl = Exercises , + name-pl = exercises , + +type = solution , + Name-sg = Solution , + name-sg = solution , + Name-pl = Solutions , + name-pl = solutions , +%% +%% +%% End of file `zref-clever-english.dict'. diff --git a/Master/texmf-dist/tex/latex/zref-clever/zref-clever-french.dict b/Master/texmf-dist/tex/latex/zref-clever/zref-clever-french.dict new file mode 100644 index 00000000000..9de1ba4d4b0 --- /dev/null +++ b/Master/texmf-dist/tex/latex/zref-clever/zref-clever-french.dict @@ -0,0 +1,262 @@ +%% +%% This is file `zref-clever-french.dict', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% zref-clever.dtx (with options: `dict-french') +%% +%% This file was generated from file(s) of the LaTeX package "zref-clever". +%% +%% Copyright (C) 2021 Gustavo Barros +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file: +%% +%% https://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 is "maintained" (as per LPPL maintenance status) by +%% Gustavo Barros. +%% +%% This work consists of the files zref-clever.dtx, +%% zref-clever.ins, +%% zref-clever.tex, +%% zref-clever-code.tex, +%% and the derived files listed in MANIFEST.md. +%% +%% The released version of this package is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the package can be found at +%% +%% https://github.com/gusbrs/zref-clever +%% +%% for those people who are interested. +%% +%% ----------------------------------------------------------------------- +%% +namesep = {\nobreakspace} , +pairsep = {~et\nobreakspace} , +listsep = {,~} , +lastsep = {~et\nobreakspace} , +tpairsep = {~et\nobreakspace} , +tlistsep = {,~} , +tlastsep = {~et\nobreakspace} , +notesep = {~} , +rangesep = {~à\nobreakspace} , + +type = book , + gender = m , + Name-sg = Livre , + name-sg = livre , + Name-pl = Livres , + name-pl = livres , + +type = part , + gender = f , + Name-sg = Partie , + name-sg = partie , + Name-pl = Parties , + name-pl = parties , + +type = chapter , + gender = m , + Name-sg = Chapitre , + name-sg = chapitre , + Name-pl = Chapitres , + name-pl = chapitres , + +type = section , + gender = f , + Name-sg = Section , + name-sg = section , + Name-pl = Sections , + name-pl = sections , + +type = paragraph , + gender = m , + Name-sg = Paragraphe , + name-sg = paragraphe , + Name-pl = Paragraphes , + name-pl = paragraphes , + +type = appendix , + gender = f , + Name-sg = Annexe , + name-sg = annexe , + Name-pl = Annexes , + name-pl = annexes , + +type = subappendix , + gender = f , + Name-sg = Annexe , + name-sg = annexe , + Name-pl = Annexes , + name-pl = annexes , + +type = page , + gender = f , + Name-sg = Page , + name-sg = page , + Name-pl = Pages , + name-pl = pages , + rangesep = {\textendash} , + +type = line , + gender = f , + Name-sg = Ligne , + name-sg = ligne , + Name-pl = Lignes , + name-pl = lignes , + +type = figure , + gender = f , + Name-sg = Figure , + name-sg = figure , + Name-pl = Figures , + name-pl = figures , + +type = table , + gender = f , + Name-sg = Table , + name-sg = table , + Name-pl = Tables , + name-pl = tables , + +type = item , + gender = m , + Name-sg = Point , + name-sg = point , + Name-pl = Points , + name-pl = points , + +type = footnote , + gender = f , + Name-sg = Note , + name-sg = note , + Name-pl = Notes , + name-pl = notes , + +type = endnote , + gender = f , + Name-sg = Note , + name-sg = note , + Name-pl = Notes , + name-pl = notes , + +type = note , + gender = f , + Name-sg = Note , + name-sg = note , + Name-pl = Notes , + name-pl = notes , + +type = equation , + gender = f , + Name-sg = Équation , + name-sg = équation , + Name-pl = Équations , + name-pl = équations , + refpre = {(} , + refpos = {)} , + +type = theorem , + gender = m , + Name-sg = Théorème , + name-sg = théorème , + Name-pl = Théorèmes , + name-pl = théorèmes , + +type = lemma , + gender = m , + Name-sg = Lemme , + name-sg = lemme , + Name-pl = Lemmes , + name-pl = lemmes , + +type = corollary , + gender = m , + Name-sg = Corollaire , + name-sg = corollaire , + Name-pl = Corollaires , + name-pl = corollaires , + +type = proposition , + gender = f , + Name-sg = Proposition , + name-sg = proposition , + Name-pl = Propositions , + name-pl = propositions , + +type = definition , + gender = f , + Name-sg = Définition , + name-sg = définition , + Name-pl = Définitions , + name-pl = définitions , + +type = proof , + gender = f , + Name-sg = Démonstration , + name-sg = démonstration , + Name-pl = Démonstrations , + name-pl = démonstrations , + +type = result , + gender = m , + Name-sg = Résultat , + name-sg = résultat , + Name-pl = Résultats , + name-pl = résultats , + +type = remark , + gender = f , + Name-sg = Remarque , + name-sg = remarque , + Name-pl = Remarques , + name-pl = remarques , + +type = example , + gender = m , + Name-sg = Exemple , + name-sg = exemple , + Name-pl = Exemples , + name-pl = exemples , + +type = algorithm , + gender = m , + Name-sg = Algorithme , + name-sg = algorithme , + Name-pl = Algorithmes , + name-pl = algorithmes , + +type = listing , + gender = f , + Name-sg = Liste , + name-sg = liste , + Name-pl = Listes , + name-pl = listes , + +type = exercise , + gender = m , + Name-sg = Exercice , + name-sg = exercice , + Name-pl = Exercices , + name-pl = exercices , + +type = solution , + gender = f , + Name-sg = Solution , + name-sg = solution , + Name-pl = Solutions , + name-pl = solutions , +%% +%% +%% End of file `zref-clever-french.dict'. diff --git a/Master/texmf-dist/tex/latex/zref-clever/zref-clever-german.dict b/Master/texmf-dist/tex/latex/zref-clever/zref-clever-german.dict new file mode 100644 index 00000000000..502e5d29a62 --- /dev/null +++ b/Master/texmf-dist/tex/latex/zref-clever/zref-clever-german.dict @@ -0,0 +1,502 @@ +%% +%% This is file `zref-clever-german.dict', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% zref-clever.dtx (with options: `dict-german') +%% +%% This file was generated from file(s) of the LaTeX package "zref-clever". +%% +%% Copyright (C) 2021 Gustavo Barros +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file: +%% +%% https://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 is "maintained" (as per LPPL maintenance status) by +%% Gustavo Barros. +%% +%% This work consists of the files zref-clever.dtx, +%% zref-clever.ins, +%% zref-clever.tex, +%% zref-clever-code.tex, +%% and the derived files listed in MANIFEST.md. +%% +%% The released version of this package is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the package can be found at +%% +%% https://github.com/gusbrs/zref-clever +%% +%% for those people who are interested. +%% +%% ----------------------------------------------------------------------- +%% +namesep = {\nobreakspace} , +pairsep = {~und\nobreakspace} , +listsep = {,~} , +lastsep = {~und\nobreakspace} , +tpairsep = {~und\nobreakspace} , +tlistsep = {,~} , +tlastsep = {~und\nobreakspace} , +notesep = {~} , +rangesep = {~bis\nobreakspace} , + +type = book , + gender = n , + case = N , + Name-sg = Buch , + Name-pl = Bücher , + case = A , + Name-sg = Buch , + Name-pl = Bücher , + case = D , + Name-sg = Buch , + Name-pl = Büchern , + case = G , + Name-sg = Buches , + Name-pl = Bücher , + +type = part , + gender = m , + case = N , + Name-sg = Teil , + Name-pl = Teile , + case = A , + Name-sg = Teil , + Name-pl = Teile , + case = D , + Name-sg = Teil , + Name-pl = Teilen , + case = G , + Name-sg = Teiles , + Name-pl = Teile , + +type = chapter , + gender = n , + case = N , + Name-sg = Kapitel , + Name-pl = Kapitel , + case = A , + Name-sg = Kapitel , + Name-pl = Kapitel , + case = D , + Name-sg = Kapitel , + Name-pl = Kapiteln , + case = G , + Name-sg = Kapitels , + Name-pl = Kapitel , + +type = section , + gender = m , + case = N , + Name-sg = Abschnitt , + Name-pl = Abschnitte , + case = A , + Name-sg = Abschnitt , + Name-pl = Abschnitte , + case = D , + Name-sg = Abschnitt , + Name-pl = Abschnitten , + case = G , + Name-sg = Abschnitts , + Name-pl = Abschnitte , + +type = paragraph , + gender = m , + case = N , + Name-sg = Absatz , + Name-pl = Absätze , + case = A , + Name-sg = Absatz , + Name-pl = Absätze , + case = D , + Name-sg = Absatz , + Name-pl = Absätzen , + case = G , + Name-sg = Absatzes , + Name-pl = Absätze , + +type = appendix , + gender = m , + case = N , + Name-sg = Anhang , + Name-pl = Anhänge , + case = A , + Name-sg = Anhang , + Name-pl = Anhänge , + case = D , + Name-sg = Anhang , + Name-pl = Anhängen , + case = G , + Name-sg = Anhangs , + Name-pl = Anhänge , + +type = subappendix , + gender = m , + case = N , + Name-sg = Anhang , + Name-pl = Anhänge , + case = A , + Name-sg = Anhang , + Name-pl = Anhänge , + case = D , + Name-sg = Anhang , + Name-pl = Anhängen , + case = G , + Name-sg = Anhangs , + Name-pl = Anhänge , + +type = page , + gender = f , + case = N , + Name-sg = Seite , + Name-pl = Seiten , + case = A , + Name-sg = Seite , + Name-pl = Seiten , + case = D , + Name-sg = Seite , + Name-pl = Seiten , + case = G , + Name-sg = Seite , + Name-pl = Seiten , + rangesep = {\textendash} , + +type = line , + gender = f , + case = N , + Name-sg = Zeile , + Name-pl = Zeilen , + case = A , + Name-sg = Zeile , + Name-pl = Zeilen , + case = D , + Name-sg = Zeile , + Name-pl = Zeilen , + case = G , + Name-sg = Zeile , + Name-pl = Zeilen , + +type = figure , + gender = f , + case = N , + Name-sg = Abbildung , + Name-pl = Abbildungen , + Name-sg-ab = Abb. , + Name-pl-ab = Abb. , + case = A , + Name-sg = Abbildung , + Name-pl = Abbildungen , + Name-sg-ab = Abb. , + Name-pl-ab = Abb. , + case = D , + Name-sg = Abbildung , + Name-pl = Abbildungen , + Name-sg-ab = Abb. , + Name-pl-ab = Abb. , + case = G , + Name-sg = Abbildung , + Name-pl = Abbildungen , + Name-sg-ab = Abb. , + Name-pl-ab = Abb. , + +type = table , + gender = f , + case = N , + Name-sg = Tabelle , + Name-pl = Tabellen , + case = A , + Name-sg = Tabelle , + Name-pl = Tabellen , + case = D , + Name-sg = Tabelle , + Name-pl = Tabellen , + case = G , + Name-sg = Tabelle , + Name-pl = Tabellen , + +type = item , + gender = m , + case = N , + Name-sg = Punkt , + Name-pl = Punkte , + case = A , + Name-sg = Punkt , + Name-pl = Punkte , + case = D , + Name-sg = Punkt , + Name-pl = Punkten , + case = G , + Name-sg = Punktes , + Name-pl = Punkte , + +type = footnote , + gender = f , + case = N , + Name-sg = Fußnote , + Name-pl = Fußnoten , + case = A , + Name-sg = Fußnote , + Name-pl = Fußnoten , + case = D , + Name-sg = Fußnote , + Name-pl = Fußnoten , + case = G , + Name-sg = Fußnote , + Name-pl = Fußnoten , + +type = endnote , + gender = f , + case = N , + Name-sg = Endnote , + Name-pl = Endnoten , + case = A , + Name-sg = Endnote , + Name-pl = Endnoten , + case = D , + Name-sg = Endnote , + Name-pl = Endnoten , + case = G , + Name-sg = Endnote , + Name-pl = Endnoten , + +type = note , + gender = f , + case = N , + Name-sg = Anmerkung , + Name-pl = Anmerkungen , + case = A , + Name-sg = Anmerkung , + Name-pl = Anmerkungen , + case = D , + Name-sg = Anmerkung , + Name-pl = Anmerkungen , + case = G , + Name-sg = Anmerkung , + Name-pl = Anmerkungen , + +type = equation , + gender = f , + case = N , + Name-sg = Gleichung , + Name-pl = Gleichungen , + case = A , + Name-sg = Gleichung , + Name-pl = Gleichungen , + case = D , + Name-sg = Gleichung , + Name-pl = Gleichungen , + case = G , + Name-sg = Gleichung , + Name-pl = Gleichungen , + refpre = {(} , + refpos = {)} , + +type = theorem , + gender = n , + case = N , + Name-sg = Theorem , + Name-pl = Theoreme , + case = A , + Name-sg = Theorem , + Name-pl = Theoreme , + case = D , + Name-sg = Theorem , + Name-pl = Theoremen , + case = G , + Name-sg = Theorems , + Name-pl = Theoreme , + +type = lemma , + gender = n , + case = N , + Name-sg = Lemma , + Name-pl = Lemmata , + case = A , + Name-sg = Lemma , + Name-pl = Lemmata , + case = D , + Name-sg = Lemma , + Name-pl = Lemmata , + case = G , + Name-sg = Lemmas , + Name-pl = Lemmata , + +type = corollary , + gender = n , + case = N , + Name-sg = Korollar , + Name-pl = Korollare , + case = A , + Name-sg = Korollar , + Name-pl = Korollare , + case = D , + Name-sg = Korollar , + Name-pl = Korollaren , + case = G , + Name-sg = Korollars , + Name-pl = Korollare , + +type = proposition , + gender = m , + case = N , + Name-sg = Satz , + Name-pl = Sätze , + case = A , + Name-sg = Satz , + Name-pl = Sätze , + case = D , + Name-sg = Satz , + Name-pl = Sätzen , + case = G , + Name-sg = Satzes , + Name-pl = Sätze , + +type = definition , + gender = f , + case = N , + Name-sg = Definition , + Name-pl = Definitionen , + case = A , + Name-sg = Definition , + Name-pl = Definitionen , + case = D , + Name-sg = Definition , + Name-pl = Definitionen , + case = G , + Name-sg = Definition , + Name-pl = Definitionen , + +type = proof , + gender = m , + case = N , + Name-sg = Beweis , + Name-pl = Beweise , + case = A , + Name-sg = Beweis , + Name-pl = Beweise , + case = D , + Name-sg = Beweis , + Name-pl = Beweisen , + case = G , + Name-sg = Beweises , + Name-pl = Beweise , + +type = result , + gender = n , + case = N , + Name-sg = Ergebnis , + Name-pl = Ergebnisse , + case = A , + Name-sg = Ergebnis , + Name-pl = Ergebnisse , + case = D , + Name-sg = Ergebnis , + Name-pl = Ergebnissen , + case = G , + Name-sg = Ergebnisses , + Name-pl = Ergebnisse , + +type = remark , + gender = f , + case = N , + Name-sg = Bemerkung , + Name-pl = Bemerkungen , + case = A , + Name-sg = Bemerkung , + Name-pl = Bemerkungen , + case = D , + Name-sg = Bemerkung , + Name-pl = Bemerkungen , + case = G , + Name-sg = Bemerkung , + Name-pl = Bemerkungen , + +type = example , + gender = n , + case = N , + Name-sg = Beispiel , + Name-pl = Beispiele , + case = A , + Name-sg = Beispiel , + Name-pl = Beispiele , + case = D , + Name-sg = Beispiel , + Name-pl = Beispielen , + case = G , + Name-sg = Beispiels , + Name-pl = Beispiele , + +type = algorithm , + gender = m , + case = N , + Name-sg = Algorithmus , + Name-pl = Algorithmen , + case = A , + Name-sg = Algorithmus , + Name-pl = Algorithmen , + case = D , + Name-sg = Algorithmus , + Name-pl = Algorithmen , + case = G , + Name-sg = Algorithmus , + Name-pl = Algorithmen , + +type = listing , + gender = n , + case = N , + Name-sg = Listing , + Name-pl = Listings , + case = A , + Name-sg = Listing , + Name-pl = Listings , + case = D , + Name-sg = Listing , + Name-pl = Listings , + case = G , + Name-sg = Listings , + Name-pl = Listings , + +type = exercise , + gender = f , + case = N , + Name-sg = Übungsaufgabe , + Name-pl = Übungsaufgaben , + case = A , + Name-sg = Übungsaufgabe , + Name-pl = Übungsaufgaben , + case = D , + Name-sg = Übungsaufgabe , + Name-pl = Übungsaufgaben , + case = G , + Name-sg = Übungsaufgabe , + Name-pl = Übungsaufgaben , + +type = solution , + gender = f , + case = N , + Name-sg = Lösung , + Name-pl = Lösungen , + case = A , + Name-sg = Lösung , + Name-pl = Lösungen , + case = D , + Name-sg = Lösung , + Name-pl = Lösungen , + case = G , + Name-sg = Lösung , + Name-pl = Lösungen , +%% +%% +%% End of file `zref-clever-german.dict'. diff --git a/Master/texmf-dist/tex/latex/zref-clever/zref-clever-portuguese.dict b/Master/texmf-dist/tex/latex/zref-clever/zref-clever-portuguese.dict new file mode 100644 index 00000000000..180a729f527 --- /dev/null +++ b/Master/texmf-dist/tex/latex/zref-clever/zref-clever-portuguese.dict @@ -0,0 +1,276 @@ +%% +%% This is file `zref-clever-portuguese.dict', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% zref-clever.dtx (with options: `dict-portuguese') +%% +%% This file was generated from file(s) of the LaTeX package "zref-clever". +%% +%% Copyright (C) 2021 Gustavo Barros +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file: +%% +%% https://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 is "maintained" (as per LPPL maintenance status) by +%% Gustavo Barros. +%% +%% This work consists of the files zref-clever.dtx, +%% zref-clever.ins, +%% zref-clever.tex, +%% zref-clever-code.tex, +%% and the derived files listed in MANIFEST.md. +%% +%% The released version of this package is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the package can be found at +%% +%% https://github.com/gusbrs/zref-clever +%% +%% for those people who are interested. +%% +%% ----------------------------------------------------------------------- +%% +namesep = {\nobreakspace} , +pairsep = {~e\nobreakspace} , +listsep = {,~} , +lastsep = {~e\nobreakspace} , +tpairsep = {~e\nobreakspace} , +tlistsep = {,~} , +tlastsep = {~e\nobreakspace} , +notesep = {~} , +rangesep = {~a\nobreakspace} , + +type = book , + gender = m , + Name-sg = Livro , + name-sg = livro , + Name-pl = Livros , + name-pl = livros , + +type = part , + gender = f , + Name-sg = Parte , + name-sg = parte , + Name-pl = Partes , + name-pl = partes , + +type = chapter , + gender = m , + Name-sg = Capítulo , + name-sg = capítulo , + Name-pl = Capítulos , + name-pl = capítulos , + +type = section , + gender = f , + Name-sg = Seção , + name-sg = seção , + Name-pl = Seções , + name-pl = seções , + +type = paragraph , + gender = m , + Name-sg = Parágrafo , + name-sg = parágrafo , + Name-pl = Parágrafos , + name-pl = parágrafos , + Name-sg-ab = Par. , + name-sg-ab = par. , + Name-pl-ab = Par. , + name-pl-ab = par. , + +type = appendix , + gender = m , + Name-sg = Apêndice , + name-sg = apêndice , + Name-pl = Apêndices , + name-pl = apêndices , + +type = subappendix , + gender = m , + Name-sg = Apêndice , + name-sg = apêndice , + Name-pl = Apêndices , + name-pl = apêndices , + +type = page , + gender = f , + Name-sg = Página , + name-sg = página , + Name-pl = Páginas , + name-pl = páginas , + name-sg-ab = p. , + name-pl-ab = pp. , + rangesep = {\textendash} , + +type = line , + gender = f , + Name-sg = Linha , + name-sg = linha , + Name-pl = Linhas , + name-pl = linhas , + +type = figure , + gender = f , + Name-sg = Figura , + name-sg = figura , + Name-pl = Figuras , + name-pl = figuras , + Name-sg-ab = Fig. , + name-sg-ab = fig. , + Name-pl-ab = Figs. , + name-pl-ab = figs. , + +type = table , + gender = f , + Name-sg = Tabela , + name-sg = tabela , + Name-pl = Tabelas , + name-pl = tabelas , + +type = item , + gender = m , + Name-sg = Item , + name-sg = item , + Name-pl = Itens , + name-pl = itens , + +type = footnote , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = endnote , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = note , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = equation , + gender = f , + Name-sg = Equação , + name-sg = equação , + Name-pl = Equações , + name-pl = equações , + Name-sg-ab = Eq. , + name-sg-ab = eq. , + Name-pl-ab = Eqs. , + name-pl-ab = eqs. , + refpre = {(} , + refpos = {)} , + +type = theorem , + gender = m , + Name-sg = Teorema , + name-sg = teorema , + Name-pl = Teoremas , + name-pl = teoremas , + +type = lemma , + gender = m , + Name-sg = Lema , + name-sg = lema , + Name-pl = Lemas , + name-pl = lemas , + +type = corollary , + gender = m , + Name-sg = Corolário , + name-sg = corolário , + Name-pl = Corolários , + name-pl = corolários , + +type = proposition , + gender = f , + Name-sg = Proposição , + name-sg = proposição , + Name-pl = Proposições , + name-pl = proposições , + +type = definition , + gender = f , + Name-sg = Definição , + name-sg = definição , + Name-pl = Definições , + name-pl = definições , + +type = proof , + gender = f , + Name-sg = Demonstração , + name-sg = demonstração , + Name-pl = Demonstrações , + name-pl = demonstrações , + +type = result , + gender = m , + Name-sg = Resultado , + name-sg = resultado , + Name-pl = Resultados , + name-pl = resultados , + +type = remark , + gender = f , + Name-sg = Observação , + name-sg = observação , + Name-pl = Observações , + name-pl = observações , + +type = example , + gender = m , + Name-sg = Exemplo , + name-sg = exemplo , + Name-pl = Exemplos , + name-pl = exemplos , + +type = algorithm , + gender = m , + Name-sg = Algoritmo , + name-sg = algoritmo , + Name-pl = Algoritmos , + name-pl = algoritmos , + +type = listing , + gender = f , + Name-sg = Listagem , + name-sg = listagem , + Name-pl = Listagens , + name-pl = listagens , + +type = exercise , + gender = m , + Name-sg = Exercício , + name-sg = exercício , + Name-pl = Exercícios , + name-pl = exercícios , + +type = solution , + gender = f , + Name-sg = Solução , + name-sg = solução , + Name-pl = Soluções , + name-pl = soluções , +%% +%% +%% End of file `zref-clever-portuguese.dict'. diff --git a/Master/texmf-dist/tex/latex/zref-clever/zref-clever-spanish.dict b/Master/texmf-dist/tex/latex/zref-clever/zref-clever-spanish.dict new file mode 100644 index 00000000000..04291ac7358 --- /dev/null +++ b/Master/texmf-dist/tex/latex/zref-clever/zref-clever-spanish.dict @@ -0,0 +1,262 @@ +%% +%% This is file `zref-clever-spanish.dict', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% zref-clever.dtx (with options: `dict-spanish') +%% +%% This file was generated from file(s) of the LaTeX package "zref-clever". +%% +%% Copyright (C) 2021 Gustavo Barros +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file: +%% +%% https://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 is "maintained" (as per LPPL maintenance status) by +%% Gustavo Barros. +%% +%% This work consists of the files zref-clever.dtx, +%% zref-clever.ins, +%% zref-clever.tex, +%% zref-clever-code.tex, +%% and the derived files listed in MANIFEST.md. +%% +%% The released version of this package is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the package can be found at +%% +%% https://github.com/gusbrs/zref-clever +%% +%% for those people who are interested. +%% +%% ----------------------------------------------------------------------- +%% +namesep = {\nobreakspace} , +pairsep = {~y\nobreakspace} , +listsep = {,~} , +lastsep = {~y\nobreakspace} , +tpairsep = {~y\nobreakspace} , +tlistsep = {,~} , +tlastsep = {~y\nobreakspace} , +notesep = {~} , +rangesep = {~a\nobreakspace} , + +type = book , + gender = m , + Name-sg = Libro , + name-sg = libro , + Name-pl = Libros , + name-pl = libros , + +type = part , + gender = f , + Name-sg = Parte , + name-sg = parte , + Name-pl = Partes , + name-pl = partes , + +type = chapter , + gender = m , + Name-sg = Capítulo , + name-sg = capítulo , + Name-pl = Capítulos , + name-pl = capítulos , + +type = section , + gender = f , + Name-sg = Sección , + name-sg = sección , + Name-pl = Secciones , + name-pl = secciones , + +type = paragraph , + gender = m , + Name-sg = Párrafo , + name-sg = párrafo , + Name-pl = Párrafos , + name-pl = párrafos , + +type = appendix , + gender = m , + Name-sg = Apéndice , + name-sg = apéndice , + Name-pl = Apéndices , + name-pl = apéndices , + +type = subappendix , + gender = m , + Name-sg = Apéndice , + name-sg = apéndice , + Name-pl = Apéndices , + name-pl = apéndices , + +type = page , + gender = f , + Name-sg = Página , + name-sg = página , + Name-pl = Páginas , + name-pl = páginas , + rangesep = {\textendash} , + +type = line , + gender = f , + Name-sg = Línea , + name-sg = línea , + Name-pl = Líneas , + name-pl = líneas , + +type = figure , + gender = f , + Name-sg = Figura , + name-sg = figura , + Name-pl = Figuras , + name-pl = figuras , + +type = table , + gender = m , + Name-sg = Cuadro , + name-sg = cuadro , + Name-pl = Cuadros , + name-pl = cuadros , + +type = item , + gender = m , + Name-sg = Punto , + name-sg = punto , + Name-pl = Puntos , + name-pl = puntos , + +type = footnote , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = endnote , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = note , + gender = f , + Name-sg = Nota , + name-sg = nota , + Name-pl = Notas , + name-pl = notas , + +type = equation , + gender = f , + Name-sg = Ecuación , + name-sg = ecuación , + Name-pl = Ecuaciones , + name-pl = ecuaciones , + refpre = {(} , + refpos = {)} , + +type = theorem , + gender = m , + Name-sg = Teorema , + name-sg = teorema , + Name-pl = Teoremas , + name-pl = teoremas , + +type = lemma , + gender = m , + Name-sg = Lema , + name-sg = lema , + Name-pl = Lemas , + name-pl = lemas , + +type = corollary , + gender = m , + Name-sg = Corolario , + name-sg = corolario , + Name-pl = Corolarios , + name-pl = corolarios , + +type = proposition , + gender = f , + Name-sg = Proposición , + name-sg = proposición , + Name-pl = Proposiciones , + name-pl = proposiciones , + +type = definition , + gender = f , + Name-sg = Definición , + name-sg = definición , + Name-pl = Definiciones , + name-pl = definiciones , + +type = proof , + gender = f , + Name-sg = Demostración , + name-sg = demostración , + Name-pl = Demostraciones , + name-pl = demostraciones , + +type = result , + gender = m , + Name-sg = Resultado , + name-sg = resultado , + Name-pl = Resultados , + name-pl = resultados , + +type = remark , + gender = f , + Name-sg = Observación , + name-sg = observación , + Name-pl = Observaciones , + name-pl = observaciones , + +type = example , + gender = m , + Name-sg = Ejemplo , + name-sg = ejemplo , + Name-pl = Ejemplos , + name-pl = ejemplos , + +type = algorithm , + gender = m , + Name-sg = Algoritmo , + name-sg = algoritmo , + Name-pl = Algoritmos , + name-pl = algoritmos , + +type = listing , + gender = m , + Name-sg = Listado , + name-sg = listado , + Name-pl = Listados , + name-pl = listados , + +type = exercise , + gender = m , + Name-sg = Ejercicio , + name-sg = ejercicio , + Name-pl = Ejercicios , + name-pl = ejercicios , + +type = solution , + gender = f , + Name-sg = Solución , + name-sg = solución , + Name-pl = Soluciones , + name-pl = soluciones , +%% +%% +%% End of file `zref-clever-spanish.dict'. diff --git a/Master/texmf-dist/tex/latex/zref-clever/zref-clever.sty b/Master/texmf-dist/tex/latex/zref-clever/zref-clever.sty new file mode 100644 index 00000000000..5728b971d1f --- /dev/null +++ b/Master/texmf-dist/tex/latex/zref-clever/zref-clever.sty @@ -0,0 +1,3519 @@ +%% +%% This is file `zref-clever.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% zref-clever.dtx (with options: `package') +%% +%% This file was generated from file(s) of the LaTeX package "zref-clever". +%% +%% Copyright (C) 2021 Gustavo Barros +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file: +%% +%% https://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 is "maintained" (as per LPPL maintenance status) by +%% Gustavo Barros. +%% +%% This work consists of the files zref-clever.dtx, +%% zref-clever.ins, +%% zref-clever.tex, +%% zref-clever-code.tex, +%% and the derived files listed in MANIFEST.md. +%% +%% The released version of this package is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the package can be found at +%% +%% https://github.com/gusbrs/zref-clever +%% +%% for those people who are interested. +%% +%% ----------------------------------------------------------------------- +%% +\providecommand\IfFormatAtLeastTF{\@ifl@t@r\fmtversion} +\IfFormatAtLeastTF{2021-11-15} + {} + {% + \PackageError{zref-clever}{LaTeX kernel too old} + {% + 'zref-clever' requires a LaTeX kernel 2021-11-15 or newer.% + \MessageBreak Loading will abort!% + }% + \endinput + }% +\ProvidesExplPackage {zref-clever} {2021-11-24} {0.1.0-alpha} + {Clever LaTeX cross-references based on zref} +\RequirePackage { zref-base } +\RequirePackage { zref-user } +\RequirePackage { zref-abspage } +\RequirePackage { l3keys2e } +\RequirePackage { ifdraft } +\zref@newprop { zc@counter } { \l__zrefclever_current_counter_tl } +\zref@addprop \ZREF@mainlist { zc@counter } +\zref@newprop { thecounter } + { + \cs_if_exist:cTF { c@ \l__zrefclever_current_counter_tl } + { \use:c { the \l__zrefclever_current_counter_tl } } + { + \cs_if_exist:cT { c@ \@currentcounter } + { \use:c { the \@currentcounter } } + } + } +\zref@addprop \ZREF@mainlist { thecounter } +\zref@newprop { zc@type } + { + \exp_args:NNe \prop_if_in:NnTF \l__zrefclever_counter_type_prop + \l__zrefclever_current_counter_tl + { + \exp_args:NNe \prop_item:Nn \l__zrefclever_counter_type_prop + { \l__zrefclever_current_counter_tl } + } + { \l__zrefclever_current_counter_tl } + } +\zref@addprop \ZREF@mainlist { zc@type } +\zref@newprop { zc@cntval } [0] + { + \cs_if_exist:cTF { c@ \l__zrefclever_current_counter_tl } + { \int_use:c { c@ \l__zrefclever_current_counter_tl } } + { + \cs_if_exist:cT { c@ \@currentcounter } + { \int_use:c { c@ \@currentcounter } } + } + } +\zref@addprop \ZREF@mainlist { zc@cntval } +\zref@newprop* { zc@pgval } [0] { \int_use:c { c@page } } +\zref@addprop \ZREF@mainlist { zc@pgval } +\cs_new:Npn \__zrefclever_get_enclosing_counters_value:n #1 + { + \cs_if_exist:cT { c@ \__zrefclever_counter_reset_by:n {#1} } + { + { \int_use:c { c@ \__zrefclever_counter_reset_by:n {#1} } } + \__zrefclever_get_enclosing_counters_value:e + { \__zrefclever_counter_reset_by:n {#1} } + } + } +\cs_generate_variant:Nn \__zrefclever_get_enclosing_counters_value:n { e } +\cs_new:Npn \__zrefclever_counter_reset_by:n #1 + { + \bool_if:nTF + { \prop_if_in_p:Nn \l__zrefclever_counter_resetby_prop {#1} } + { \prop_item:Nn \l__zrefclever_counter_resetby_prop {#1} } + { + \seq_map_tokens:Nn \l__zrefclever_counter_resetters_seq + { \__zrefclever_counter_reset_by_aux:nn {#1} } + } + } +\cs_new:Npn \__zrefclever_counter_reset_by_aux:nn #1#2 + { + \cs_if_exist:cT { c@ #2 } + { + \tl_if_empty:cF { cl@ #2 } + { + \tl_map_tokens:cn { cl@ #2 } + { \__zrefclever_counter_reset_by_auxi:nnn {#2} {#1} } + } + } + } +\cs_new:Npn \__zrefclever_counter_reset_by_auxi:nnn #1#2#3 + { + \str_if_eq:nnT {#2} {#3} + { \tl_map_break:n { \seq_map_break:n {#1} } } + } +\zref@newprop { zc@enclval } + { + \__zrefclever_get_enclosing_counters_value:e + \l__zrefclever_current_counter_tl + } +\zref@addprop \ZREF@mainlist { zc@enclval } +\tl_new:N \g__zrefclever_page_format_tl +\cs_new_protected:Npx \__zrefclever_page_format_aux: { \int_eval:n { 1 } } +\AddToHook { shipout / before } + { + \group_begin: + \cs_set_eq:NN \c@page \__zrefclever_page_format_aux: + \tl_gset:Nx \g__zrefclever_page_format_tl { \thepage } + \group_end: + } +\zref@newprop* { zc@pgfmt } { \g__zrefclever_page_format_tl } +\zref@addprop \ZREF@mainlist { zc@pgfmt } +\prg_new_conditional:Npnn \__zrefclever_if_package_loaded:n #1 { T , F , TF } + { \IfPackageLoadedTF {#1} { \prg_return_true: } { \prg_return_false: } } +\prg_new_conditional:Npnn \__zrefclever_if_class_loaded:n #1 { T , F , TF } + { \IfClassLoadedTF {#1} { \prg_return_true: } { \prg_return_false: } } +\msg_new:nnn { zref-clever } { option-not-type-specific } + { + Option~'#1'~is~not~type-specific~\msg_line_context:.~ + Set~it~in~'\iow_char:N\\zcLanguageSetup'~before~first~'type'~ + switch~or~as~package~option. + } +\msg_new:nnn { zref-clever } { option-only-type-specific } + { + No~type~specified~for~option~'#1'~\msg_line_context:.~ + Set~it~after~'type'~switch. + } +\msg_new:nnn { zref-clever } { key-requires-value } + { The~'#1'~key~'#2'~requires~a~value~\msg_line_context:. } +\msg_new:nnn { zref-clever } { language-declared } + { Language~'#1'~is~already~declared~\msg_line_context:.~Nothing~to~do. } +\msg_new:nnn { zref-clever } { unknown-language-alias } + { + Language~'#1'~is~unknown~\msg_line_context:.~Can't~alias~to~it.~ + See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ + '\iow_char:N\\zcDeclareLanguageAlias'. + } +\msg_new:nnn { zref-clever } { unknown-language-setup } + { + Language~'#1'~is~unknown~\msg_line_context:.~Can't~set~it~up.~ + See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ + '\iow_char:N\\zcDeclareLanguageAlias'. + } +\msg_new:nnn { zref-clever } { unknown-language-opt } + { + Language~'#1'~is~unknown~\msg_line_context:.~Using~default.~ + See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ + '\iow_char:N\\zcDeclareLanguageAlias'. + } +\msg_new:nnn { zref-clever } { unknown-language-decl } + { + Can't~set~declension~'#1'~for~unknown~language~'#2'~\msg_line_context:.~ + See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ + '\iow_char:N\\zcDeclareLanguageAlias'. + } +\msg_new:nnn { zref-clever } { language-no-decl-ref } + { + Language~'#1'~has~no~declared~declension~cases~\msg_line_context:.~ + Nothing~to~do~with~option~'d=#2'. + } +\msg_new:nnn { zref-clever } { language-no-gender } + { + Language~'#1'~has~no~declared~gender~\msg_line_context:.~ + Nothing~to~do~with~option~'#2=#3'. + } +\msg_new:nnn { zref-clever } { language-no-decl-setup } + { + Language~'#1'~has~no~declared~declension~cases~\msg_line_context:.~ + Nothing~to~do~with~option~'case=#2'. + } +\msg_new:nnn { zref-clever } { unknown-decl-case } + { + Declension~case~'#1'~unknown~for~language~'#2'~\msg_line_context:.~ + Using~default~declension~case. + } +\msg_new:nnn { zref-clever } { nudge-multitype } + { + Reference~with~multiple~types~\msg_line_context:.~ + You~may~wish~to~separate~them~or~review~language~around~it. + } +\msg_new:nnn { zref-clever } { nudge-comptosing } + { + Multiple~labels~have~been~compressed~into~singular~type~name~ + for~type~'#1'~\msg_line_context:. + } +\msg_new:nnn { zref-clever } { nudge-plural-when-sg } + { + Option~'sg'~signals~that~a~singular~type~name~was~expected~ + \msg_line_context:.~But~type~'#1'~has~plural~type~name. + } +\msg_new:nnn { zref-clever } { gender-not-declared } + { Language~'#1'~has~no~'#2'~gender~declared~\msg_line_context:. } +\msg_new:nnn { zref-clever } { nudge-gender-mismatch } + { + Gender~mismatch~for~type~'#1'~\msg_line_context:.~ + You've~specified~'g=#2'~but~type~name~is~'#3'~for~language~'#4'. + } +\msg_new:nnn { zref-clever } { nudge-gender-not-declared-for-type } + { + You've~specified~'g=#1'~\msg_line_context:.~ + But~gender~for~type~'#2'~is~not~declared~for~language~'#3'. + } +\msg_new:nnn { zref-clever } { nudgeif-unknown-value } + { Unknown~value~'#1'~for~'nudgeif'~option~\msg_line_context:. } +\msg_new:nnn { zref-clever } { option-document-only } + { Option~'#1'~is~only~available~after~\iow_char:N\\begin\{document\}. } +\msg_new:nnn { zref-clever } { dict-loaded } + { Loaded~'#1'~dictionary. } +\msg_new:nnn { zref-clever } { dict-not-available } + { Dictionary~for~'#1'~not~available~\msg_line_context:. } +\msg_new:nnn { zref-clever } { unknown-language-load } + { + Language~'#1'~is~unknown~\msg_line_context:.~Unable~to~load~dictionary.~ + See~documentation~for~'\iow_char:N\\zcDeclareLanguage'~and~ + '\iow_char:N\\zcDeclareLanguageAlias'. + } +\msg_new:nnn { zref-clever } { zref-property-undefined } + { + Option~'ref=#1'~requested~\msg_line_context:.~ + But~the~property~'#1'~is~not~declared,~falling-back~to~'default'. + } +\msg_new:nnn { zref-clever } { hyperref-preamble-only } + { + Option~'hyperref'~only~available~in~the~preamble~\msg_line_context:.~ + To~inhibit~hyperlinking~locally,~you~can~use~the~starred~version~of~ + '\iow_char:N\\zcref'. + } +\msg_new:nnn { zref-clever } { missing-hyperref } + { Missing~'hyperref'~package.~Setting~'hyperref=false'. } +\msg_new:nnn { zref-clever } { titleref-preamble-only } + { + Option~'titleref'~only~available~in~the~preamble~\msg_line_context:.~ + Did~you~mean~'ref=title'?. + } +\msg_new:nnn { zref-clever } { option-preamble-only } + { Option~'#1'~only~available~in~the~preamble~\msg_line_context:. } +\msg_new:nnn { zref-clever } { unknown-compat-module } + { + Unknown~compatibility~module~'#1'~given~to~option~'nocompat'.~ + Nothing~to~do. + } +\msg_new:nnn { zref-clever } { missing-zref-check } + { + Option~'check'~requested~\msg_line_context:.~ + But~package~'zref-check'~is~not~loaded,~can't~run~the~checks. + } +\msg_new:nnn { zref-clever } { missing-type } + { Reference~type~undefined~for~label~'#1'~\msg_line_context:. } +\msg_new:nnn { zref-clever } { missing-property } + { Reference~property~'#1'~undefined~for~label~'#2'~\msg_line_context:. } +\msg_new:nnn { zref-clever } { missing-name } + { Reference~format~option~'#1'~undefined~for~type~'#2'~\msg_line_context:. } +\msg_new:nnn { zref-clever } { missing-string } + { + We~couldn't~find~a~value~for~reference~option~'#1'~\msg_line_context:.~ + But~we~should~have:~throw~a~rock~at~the~maintainer. + } +\msg_new:nnn { zref-clever } { single-element-range } + { Range~for~type~'#1'~resulted~in~single~element~\msg_line_context:. } +\msg_new:nnn { zref-clever } { compat-package } + { Loaded~support~for~'#1'~package. } +\msg_new:nnn { zref-clever } { compat-class } + { Loaded~support~for~'#1'~documentclass. } +\cs_new_protected:Npn \__zrefclever_def_extract:Nnnn #1#2#3#4 + { + \exp_args:NNNo \exp_args:NNo \tl_set:Nn #1 + { \zref@extractdefault {#2} {#3} {#4} } + } +\cs_generate_variant:Nn \__zrefclever_def_extract:Nnnn { NVnn } +\cs_new:Npn \__zrefclever_extract_unexp:nnn #1#2#3 + { + \exp_args:NNo \exp_args:No + \exp_not:n { \zref@extractdefault {#1} {#2} {#3} } + } +\cs_generate_variant:Nn \__zrefclever_extract_unexp:nnn { Vnn , nvn , Vvn } +\cs_new:Npn \__zrefclever_extract:nnn #1#2#3 + { \zref@extractdefault {#1} {#2} {#3} } +\tl_new:N \l__zrefclever_setup_type_tl +\tl_new:N \l__zrefclever_dict_language_tl +\tl_new:N \l__zrefclever_dict_decl_case_tl +\seq_new:N \l__zrefclever_dict_declension_seq +\seq_new:N \l__zrefclever_dict_gender_seq +\seq_const_from_clist:Nn + \c__zrefclever_ref_options_necessarily_not_type_specific_seq + { + tpairsep , + tlistsep , + tlastsep , + notesep , + } +\seq_const_from_clist:Nn + \c__zrefclever_ref_options_possibly_type_specific_seq + { + namesep , + pairsep , + listsep , + lastsep , + rangesep , + refpre , + refpos , + } +\seq_const_from_clist:Nn + \c__zrefclever_ref_options_type_names_seq + { + Name-sg , + name-sg , + Name-pl , + name-pl , + Name-sg-ab , + name-sg-ab , + Name-pl-ab , + name-pl-ab , + } +\seq_const_from_clist:Nn + \c__zrefclever_ref_options_font_seq + { + namefont , + reffont , + } +\seq_new:N \c__zrefclever_ref_options_typesetup_seq +\seq_gconcat:NNN \c__zrefclever_ref_options_typesetup_seq + \c__zrefclever_ref_options_possibly_type_specific_seq + \c__zrefclever_ref_options_type_names_seq +\seq_gconcat:NNN \c__zrefclever_ref_options_typesetup_seq + \c__zrefclever_ref_options_typesetup_seq + \c__zrefclever_ref_options_font_seq +\seq_new:N \c__zrefclever_ref_options_reference_seq +\seq_gconcat:NNN \c__zrefclever_ref_options_reference_seq + \c__zrefclever_ref_options_necessarily_not_type_specific_seq + \c__zrefclever_ref_options_possibly_type_specific_seq +\seq_gconcat:NNN \c__zrefclever_ref_options_reference_seq + \c__zrefclever_ref_options_reference_seq + \c__zrefclever_ref_options_font_seq +\prop_new:N \g__zrefclever_languages_prop +\NewDocumentCommand \zcDeclareLanguage { O { } m } + { + \group_begin: + \tl_if_empty:nF {#2} + { + \prop_if_in:NnTF \g__zrefclever_languages_prop {#2} + { \msg_warning:nnn { zref-clever } { language-declared } {#2} } + { + \prop_gput:Nnn \g__zrefclever_languages_prop {#2} {#2} + \prop_new:c { g__zrefclever_dict_ #2 _prop } + \tl_set:Nn \l__zrefclever_dict_language_tl {#2} + \keys_set:nn { zref-clever / declarelang } {#1} + } + } + \group_end: + } +\@onlypreamble \zcDeclareLanguage +\NewDocumentCommand \zcDeclareLanguageAlias { m m } + { + \tl_if_empty:nF {#1} + { + \prop_if_in:NnTF \g__zrefclever_languages_prop {#2} + { + \exp_args:NNnx + \prop_gput:Nnn \g__zrefclever_languages_prop {#1} + { \prop_item:Nn \g__zrefclever_languages_prop {#2} } + } + { \msg_warning:nnn { zref-clever } { unknown-language-alias } {#2} } + } + } +\@onlypreamble \zcDeclareLanguageAlias +\keys_define:nn { zref-clever / declarelang } + { + declension .code:n = + { + \prop_gput:cnn + { g__zrefclever_dict_ \l__zrefclever_dict_language_tl _prop } + { declension } {#1} + } , + declension .value_required:n = true , + gender .code:n = + { + \prop_gput:cnn + { g__zrefclever_dict_ \l__zrefclever_dict_language_tl _prop } + { gender } {#1} + } , + gender .value_required:n = true , + allcaps .code:n = + { + \prop_gput:cnn + { g__zrefclever_dict_ \l__zrefclever_dict_language_tl _prop } + { allcaps } { true } + } , + allcaps .value_forbidden:n = true , + } +\cs_new_protected:Npn \__zrefclever_process_language_options: + { + \exp_args:NNx \prop_get:NnNTF \g__zrefclever_languages_prop + { \l__zrefclever_ref_language_tl } + \l__zrefclever_dict_language_tl + { + \exp_args:NNx \seq_set_from_clist:Nn + \l__zrefclever_dict_declension_seq + { + \prop_item:cn + { + g__zrefclever_dict_ + \l__zrefclever_dict_language_tl _prop + } + { declension } + } + \seq_if_empty:NTF \l__zrefclever_dict_declension_seq + { + \tl_if_empty:NF \l__zrefclever_ref_decl_case_tl + { + \msg_warning:nnxx { zref-clever } + { language-no-decl-ref } + { \l__zrefclever_ref_language_tl } + { \l__zrefclever_ref_decl_case_tl } + \tl_clear:N \l__zrefclever_ref_decl_case_tl + } + } + { + \tl_if_empty:NTF \l__zrefclever_ref_decl_case_tl + { + \seq_get_left:NN \l__zrefclever_dict_declension_seq + \l__zrefclever_ref_decl_case_tl + } + { + \seq_if_in:NVF \l__zrefclever_dict_declension_seq + \l__zrefclever_ref_decl_case_tl + { + \msg_warning:nnxx { zref-clever } + { unknown-decl-case } + { \l__zrefclever_ref_decl_case_tl } + { \l__zrefclever_ref_language_tl } + \seq_get_left:NN \l__zrefclever_dict_declension_seq + \l__zrefclever_ref_decl_case_tl + } + } + } + \exp_args:NNx \seq_set_from_clist:Nn + \l__zrefclever_dict_gender_seq + { + \prop_item:cn + { + g__zrefclever_dict_ + \l__zrefclever_dict_language_tl _prop + } + { gender } + } + \seq_if_empty:NTF \l__zrefclever_dict_gender_seq + { + \tl_if_empty:NF \l__zrefclever_ref_gender_tl + { + \msg_warning:nnxxx { zref-clever } + { language-no-gender } + { \l__zrefclever_ref_language_tl } + { g } + { \l__zrefclever_ref_gender_tl } + \tl_clear:N \l__zrefclever_ref_gender_tl + } + } + { + \tl_if_empty:NF \l__zrefclever_ref_gender_tl + { + \seq_if_in:NVF \l__zrefclever_dict_gender_seq + \l__zrefclever_ref_gender_tl + { + \msg_warning:nnxx { zref-clever } + { gender-not-declared } + { \l__zrefclever_ref_language_tl } + { \l__zrefclever_ref_gender_tl } + \tl_clear:N \l__zrefclever_ref_gender_tl + } + } + } + \str_if_eq:eeT + { + \prop_item:cn + { + g__zrefclever_dict_ + \l__zrefclever_dict_language_tl _prop + } + { allcaps } + } + { true } + { \bool_set_true:N \l__zrefclever_capitalize_bool } + } + { + \tl_if_empty:NF \l__zrefclever_ref_decl_case_tl + { + \msg_warning:nnxx { zref-clever } { unknown-language-decl } + { \l__zrefclever_ref_decl_case_tl } + { \l__zrefclever_ref_language_tl } + \tl_clear:N \l__zrefclever_ref_decl_case_tl + } + \tl_if_empty:NF \l__zrefclever_ref_gender_tl + { + \msg_warning:nnxxx { zref-clever } + { language-no-gender } + { \l__zrefclever_ref_language_tl } + { g } + { \l__zrefclever_ref_gender_tl } + \tl_clear:N \l__zrefclever_ref_gender_tl + } + } + } +\seq_new:N \g__zrefclever_loaded_dictionaries_seq +\bool_new:N \l__zrefclever_load_dict_verbose_bool +\cs_new_protected:Npn \__zrefclever_provide_dictionary:n #1 + { + \group_begin: + \@bsphack + \prop_get:NnNTF \g__zrefclever_languages_prop {#1} + \l__zrefclever_dict_language_tl + { + \seq_if_in:NVF + \g__zrefclever_loaded_dictionaries_seq + \l__zrefclever_dict_language_tl + { + \exp_args:Nx \file_get:nnNTF + { zref-clever- \l__zrefclever_dict_language_tl .dict } + { \ExplSyntaxOn } + \l_tmpa_tl + { + \tl_clear:N \l__zrefclever_setup_type_tl + \exp_args:NNx \seq_set_from_clist:Nn + \l__zrefclever_dict_declension_seq + { + \prop_item:cn + { + g__zrefclever_dict_ + \l__zrefclever_dict_language_tl _prop + } + { declension } + } + \seq_if_empty:NTF \l__zrefclever_dict_declension_seq + { \tl_clear:N \l__zrefclever_dict_decl_case_tl } + { + \seq_get_left:NN \l__zrefclever_dict_declension_seq + \l__zrefclever_dict_decl_case_tl + } + \exp_args:NNx \seq_set_from_clist:Nn + \l__zrefclever_dict_gender_seq + { + \prop_item:cn + { + g__zrefclever_dict_ + \l__zrefclever_dict_language_tl _prop + } + { gender } + } + \keys_set:nV { zref-clever / dictionary } \l_tmpa_tl + \seq_gput_right:NV \g__zrefclever_loaded_dictionaries_seq + \l__zrefclever_dict_language_tl + \msg_note:nnx { zref-clever } { dict-loaded } + { \l__zrefclever_dict_language_tl } + } + { + \bool_if:NT \l__zrefclever_load_dict_verbose_bool + { + \msg_warning:nnx { zref-clever } { dict-not-available } + { \l__zrefclever_dict_language_tl } + } + \seq_gput_right:NV \g__zrefclever_loaded_dictionaries_seq + \l__zrefclever_dict_language_tl + } + } + } + { + \bool_if:NT \l__zrefclever_load_dict_verbose_bool + { \msg_warning:nnn { zref-clever } { unknown-language-load } {#1} } + } + \@esphack + \group_end: + } +\cs_generate_variant:Nn \__zrefclever_provide_dictionary:n { x } +\cs_new_protected:Npn \__zrefclever_provide_dictionary_verbose:n #1 + { + \group_begin: + \bool_set_true:N \l__zrefclever_load_dict_verbose_bool + \__zrefclever_provide_dictionary:n {#1} + \group_end: + } +\cs_generate_variant:Nn \__zrefclever_provide_dictionary_verbose:n { x } +\cs_new_protected:Npn \__zrefclever_provide_dict_type_transl:nn #1#2 + { + \exp_args:Nnx \prop_gput_if_new:cnn + { g__zrefclever_dict_ \l__zrefclever_dict_language_tl _prop } + { type- \l__zrefclever_setup_type_tl - #1 } {#2} + } +\cs_new_protected:Npn \__zrefclever_provide_dict_default_transl:nn #1#2 + { + \prop_gput_if_new:cnn + { g__zrefclever_dict_ \l__zrefclever_dict_language_tl _prop } + { default- #1 } {#2} + } +\keys_define:nn { zref-clever / dictionary } + { + type .code:n = + { + \tl_if_empty:nTF {#1} + { \tl_clear:N \l__zrefclever_setup_type_tl } + { \tl_set:Nn \l__zrefclever_setup_type_tl {#1} } + } , + case .code:n = + { + \seq_if_empty:NTF \l__zrefclever_dict_declension_seq + { + \msg_info:nnxx { zref-clever } { language-no-decl-setup } + { \l__zrefclever_dict_language_tl } {#1} + } + { + \seq_if_in:NnTF \l__zrefclever_dict_declension_seq {#1} + { \tl_set:Nn \l__zrefclever_dict_decl_case_tl {#1} } + { + \msg_info:nnxx { zref-clever } { unknown-decl-case } + {#1} { \l__zrefclever_dict_language_tl } + \seq_get_left:NN \l__zrefclever_dict_declension_seq + \l__zrefclever_dict_decl_case_tl + } + } + } , + case .value_required:n = true , + gender .code:n = + { + \seq_if_empty:NTF \l__zrefclever_dict_gender_seq + { + \msg_info:nnxxx { zref-clever } { language-no-gender } + { \l__zrefclever_dict_language_tl } { gender } {#1} + } + { + \tl_if_empty:NTF \l__zrefclever_setup_type_tl + { + \msg_info:nnn { zref-clever } + { option-only-type-specific } { gender } + } + { + \seq_if_in:NnTF \l__zrefclever_dict_gender_seq {#1} + { \__zrefclever_provide_dict_type_transl:nn { gender } {#1} } + { + \msg_info:nnxx { zref-clever } { gender-not-declared } + { \l__zrefclever_dict_language_tl } {#1} + } + } + } + } , + gender .value_required:n = true , + } +\seq_map_inline:Nn + \c__zrefclever_ref_options_necessarily_not_type_specific_seq + { + \keys_define:nn { zref-clever / dictionary } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l__zrefclever_setup_type_tl + { \__zrefclever_provide_dict_default_transl:nn {#1} {##1} } + { + \msg_info:nnn { zref-clever } + { option-not-type-specific } {#1} + } + } , + } + } +\seq_map_inline:Nn + \c__zrefclever_ref_options_possibly_type_specific_seq + { + \keys_define:nn { zref-clever / dictionary } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l__zrefclever_setup_type_tl + { \__zrefclever_provide_dict_default_transl:nn {#1} {##1} } + { \__zrefclever_provide_dict_type_transl:nn {#1} {##1} } + } , + } + } +\seq_map_inline:Nn + \c__zrefclever_ref_options_type_names_seq + { + \keys_define:nn { zref-clever / dictionary } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l__zrefclever_setup_type_tl + { + \msg_info:nnn { zref-clever } + { option-only-type-specific } {#1} + } + { + \tl_if_empty:NTF \l__zrefclever_dict_decl_case_tl + { \__zrefclever_provide_dict_type_transl:nn {#1} {##1} } + { + \__zrefclever_provide_dict_type_transl:nn + { \l__zrefclever_dict_decl_case_tl - #1 } {##1} + } + } + } , + } + } +\prop_new:N \g__zrefclever_fallback_dict_prop +\prop_gset_from_keyval:Nn \g__zrefclever_fallback_dict_prop + { + tpairsep = {,~} , + tlistsep = {,~} , + tlastsep = {,~} , + notesep = {~} , + namesep = {\nobreakspace} , + pairsep = {,~} , + listsep = {,~} , + lastsep = {,~} , + rangesep = {\textendash} , + refpre = {} , + refpos = {} , + } +\prg_new_protected_conditional:Npnn + \__zrefclever_get_type_transl:nnnN #1#2#3#4 { F } + { + \prop_get:NnNTF \g__zrefclever_languages_prop {#1} + \l__zrefclever_dict_language_tl + { + \prop_get:cnNTF + { g__zrefclever_dict_ \l__zrefclever_dict_language_tl _prop } + { type- #2 - #3 } #4 + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn + \__zrefclever_get_type_transl:nnnN { xxxN , xxnN } { F } +\prg_new_protected_conditional:Npnn + \__zrefclever_get_default_transl:nnN #1#2#3 { F } + { + \prop_get:NnNTF \g__zrefclever_languages_prop {#1} + \l__zrefclever_dict_language_tl + { + \prop_get:cnNTF + { g__zrefclever_dict_ \l__zrefclever_dict_language_tl _prop } + { default- #2 } #3 + { \prg_return_true: } + { \prg_return_false: } + } + { \prg_return_false: } + } +\prg_generate_conditional_variant:Nnn + \__zrefclever_get_default_transl:nnN { xnN } { F } +\prg_new_protected_conditional:Npnn + \__zrefclever_get_fallback_transl:nN #1#2 { F } + { + \prop_get:NnNTF \g__zrefclever_fallback_dict_prop + { #1 } #2 + { \prg_return_true: } + { \prg_return_false: } + } +\cs_new_protected:Npn \__zrefclever_prop_put_non_empty:Nnn #1#2#3 + { + \tl_if_empty:nTF {#3} + { \prop_remove:Nn #1 {#2} } + { \prop_put:Nnn #1 {#2} {#3} } + } +\tl_new:N \l__zrefclever_ref_property_tl +\keys_define:nn { zref-clever / reference } + { + ref .code:n = + { + \zref@ifpropundefined {#1} + { + \msg_warning:nnn { zref-clever } { zref-property-undefined } {#1} + \tl_set:Nn \l__zrefclever_ref_property_tl { default } + } + { \tl_set:Nn \l__zrefclever_ref_property_tl {#1} } + } , + ref .initial:n = default , + ref .value_required:n = true , + page .meta:n = { ref = page }, + page .value_forbidden:n = true , + } +\bool_new:N \l__zrefclever_typeset_ref_bool +\bool_new:N \l__zrefclever_typeset_name_bool +\keys_define:nn { zref-clever / reference } + { + typeset .choice: , + typeset / both .code:n = + { + \bool_set_true:N \l__zrefclever_typeset_ref_bool + \bool_set_true:N \l__zrefclever_typeset_name_bool + } , + typeset / ref .code:n = + { + \bool_set_true:N \l__zrefclever_typeset_ref_bool + \bool_set_false:N \l__zrefclever_typeset_name_bool + } , + typeset / name .code:n = + { + \bool_set_false:N \l__zrefclever_typeset_ref_bool + \bool_set_true:N \l__zrefclever_typeset_name_bool + } , + typeset .initial:n = both , + typeset .value_required:n = true , + + noname .meta:n = { typeset = ref } , + noname .value_forbidden:n = true , + noref .meta:n = { typeset = name } , + noref .value_forbidden:n = true , + } +\bool_new:N \l__zrefclever_typeset_sort_bool +\keys_define:nn { zref-clever / reference } + { + sort .bool_set:N = \l__zrefclever_typeset_sort_bool , + sort .initial:n = true , + sort .default:n = true , + nosort .meta:n = { sort = false }, + nosort .value_forbidden:n = true , + } +\seq_new:N \l__zrefclever_typesort_seq +\keys_define:nn { zref-clever / reference } + { + typesort .code:n = + { + \seq_set_from_clist:Nn \l__zrefclever_typesort_seq {#1} + \seq_reverse:N \l__zrefclever_typesort_seq + } , + typesort .initial:n = + { part , chapter , section , paragraph }, + typesort .value_required:n = true , + notypesort .code:n = + { \seq_clear:N \l__zrefclever_typesort_seq } , + notypesort .value_forbidden:n = true , + } +\bool_new:N \l__zrefclever_typeset_compress_bool +\keys_define:nn { zref-clever / reference } + { + comp .bool_set:N = \l__zrefclever_typeset_compress_bool , + comp .initial:n = true , + comp .default:n = true , + nocomp .meta:n = { comp = false }, + nocomp .value_forbidden:n = true , + } +\bool_new:N \l__zrefclever_typeset_range_bool +\keys_define:nn { zref-clever / reference } + { + range .bool_set:N = \l__zrefclever_typeset_range_bool , + range .initial:n = false , + range .default:n = true , + } +\bool_new:N \l__zrefclever_capitalize_bool +\bool_new:N \l__zrefclever_capitalize_first_bool +\keys_define:nn { zref-clever / reference } + { + cap .bool_set:N = \l__zrefclever_capitalize_bool , + cap .initial:n = false , + cap .default:n = true , + nocap .meta:n = { cap = false }, + nocap .value_forbidden:n = true , + + capfirst .bool_set:N = \l__zrefclever_capitalize_first_bool , + capfirst .initial:n = false , + capfirst .default:n = true , + } +\bool_new:N \l__zrefclever_abbrev_bool +\bool_new:N \l__zrefclever_noabbrev_first_bool +\keys_define:nn { zref-clever / reference } + { + abbrev .bool_set:N = \l__zrefclever_abbrev_bool , + abbrev .initial:n = false , + abbrev .default:n = true , + noabbrev .meta:n = { abbrev = false }, + noabbrev .value_forbidden:n = true , + + noabbrevfirst .bool_set:N = \l__zrefclever_noabbrev_first_bool , + noabbrevfirst .initial:n = false , + noabbrevfirst .default:n = true , + } +\keys_define:nn { zref-clever / reference } + { + S .meta:n = + { capfirst = true , noabbrevfirst = true }, + S .value_forbidden:n = true , + } +\bool_new:N \l__zrefclever_use_hyperref_bool +\bool_new:N \l__zrefclever_warn_hyperref_bool +\keys_define:nn { zref-clever / reference } + { + hyperref .choice: , + hyperref / auto .code:n = + { + \bool_set_true:N \l__zrefclever_use_hyperref_bool + \bool_set_false:N \l__zrefclever_warn_hyperref_bool + } , + hyperref / true .code:n = + { + \bool_set_true:N \l__zrefclever_use_hyperref_bool + \bool_set_true:N \l__zrefclever_warn_hyperref_bool + } , + hyperref / false .code:n = + { + \bool_set_false:N \l__zrefclever_use_hyperref_bool + \bool_set_false:N \l__zrefclever_warn_hyperref_bool + } , + hyperref .initial:n = auto , + hyperref .default:n = auto + } +\AddToHook { begindocument } + { + \__zrefclever_if_package_loaded:nTF { hyperref } + { + \bool_if:NT \l__zrefclever_use_hyperref_bool + { \RequirePackage { zref-hyperref } } + } + { + \bool_if:NT \l__zrefclever_warn_hyperref_bool + { \msg_warning:nn { zref-clever } { missing-hyperref } } + \bool_set_false:N \l__zrefclever_use_hyperref_bool + } + \keys_define:nn { zref-clever / reference } + { + hyperref .code:n = + { \msg_warning:nn { zref-clever } { hyperref-preamble-only } } + } + } +\str_new:N \l__zrefclever_nameinlink_str +\keys_define:nn { zref-clever / reference } + { + nameinlink .choice: , + nameinlink / true .code:n = + { \str_set:Nn \l__zrefclever_nameinlink_str { true } } , + nameinlink / false .code:n = + { \str_set:Nn \l__zrefclever_nameinlink_str { false } } , + nameinlink / single .code:n = + { \str_set:Nn \l__zrefclever_nameinlink_str { single } } , + nameinlink / tsingle .code:n = + { \str_set:Nn \l__zrefclever_nameinlink_str { tsingle } } , + nameinlink .initial:n = tsingle , + nameinlink .default:n = true , + } +\bool_new:N \l__zrefclever_preposinlink_bool +\keys_define:nn { zref-clever / reference } + { + preposinlink .bool_set:N = \l__zrefclever_preposinlink_bool , + preposinlink .initial:n = false , + preposinlink .default:n = true , + } + +\tl_new:N \l__zrefclever_ref_language_tl +\tl_new:N \l__zrefclever_current_language_tl +\tl_new:N \l__zrefclever_main_language_tl +\AddToHook { begindocument } + { + \__zrefclever_if_package_loaded:nTF { babel } + { + \tl_set:Nn \l__zrefclever_current_language_tl { \languagename } + \tl_set:Nn \l__zrefclever_main_language_tl { \bbl@main@language } + } + { + \__zrefclever_if_package_loaded:nTF { polyglossia } + { + \tl_set:Nn \l__zrefclever_current_language_tl { \babelname } + \tl_set:Nn \l__zrefclever_main_language_tl { \mainbabelname } + } + { + \tl_set:Nn \l__zrefclever_current_language_tl { english } + \tl_set:Nn \l__zrefclever_main_language_tl { english } + } + } + \tl_set:Nn \l__zrefclever_ref_language_tl + { \l__zrefclever_current_language_tl } + } +\keys_define:nn { zref-clever / reference } + { + lang .code:n = + { + \AddToHook { begindocument } + { + \str_case:nnF {#1} + { + { current } + { + \tl_set:Nn \l__zrefclever_ref_language_tl + { \l__zrefclever_current_language_tl } + \__zrefclever_provide_dictionary_verbose:x + { \l__zrefclever_ref_language_tl } + } + + { main } + { + \tl_set:Nn \l__zrefclever_ref_language_tl + { \l__zrefclever_main_language_tl } + \__zrefclever_provide_dictionary_verbose:x + { \l__zrefclever_ref_language_tl } + } + } + { + \prop_if_in:NnTF \g__zrefclever_languages_prop {#1} + { \tl_set:Nn \l__zrefclever_ref_language_tl {#1} } + { + \msg_warning:nnn { zref-clever } + { unknown-language-opt } {#1} + \tl_set:Nn \l__zrefclever_ref_language_tl + { \l__zrefclever_current_language_tl } + } + \__zrefclever_provide_dictionary_verbose:x + { \l__zrefclever_ref_language_tl } + } + } + } , + lang .value_required:n = true , + } +\AddToHook { begindocument / before } + { + \AddToHook { begindocument } + { + \__zrefclever_provide_dictionary:x { \l__zrefclever_ref_language_tl } + \keys_define:nn { zref-clever / reference } + { + lang .code:n = + { + \str_case:nnF {#1} + { + { current } + { + \tl_set:Nn \l__zrefclever_ref_language_tl + { \l__zrefclever_current_language_tl } + \__zrefclever_provide_dictionary:x + { \l__zrefclever_ref_language_tl } + } + + { main } + { + \tl_set:Nn \l__zrefclever_ref_language_tl + { \l__zrefclever_main_language_tl } + \__zrefclever_provide_dictionary:x + { \l__zrefclever_ref_language_tl } + } + } + { + \prop_if_in:NnTF \g__zrefclever_languages_prop {#1} + { \tl_set:Nn \l__zrefclever_ref_language_tl {#1} } + { + \msg_warning:nnn { zref-clever } + { unknown-language-opt } {#1} + \tl_set:Nn \l__zrefclever_ref_language_tl + { \l__zrefclever_current_language_tl } + } + \__zrefclever_provide_dictionary:x + { \l__zrefclever_ref_language_tl } + } + } , + lang .value_required:n = true , + } + } + } +\tl_new:N \l__zrefclever_ref_decl_case_tl +\keys_define:nn { zref-clever / reference } + { + d .code:n = + { \msg_warning:nnn { zref-clever } { option-document-only } { d } } , + } +\AddToHook { begindocument } + { + \keys_define:nn { zref-clever / reference } + { + d .tl_set:N = \l__zrefclever_ref_decl_case_tl , + d .value_required:n = true , + } + } +\bool_new:N \l__zrefclever_nudge_enabled_bool +\bool_new:N \l__zrefclever_nudge_multitype_bool +\bool_new:N \l__zrefclever_nudge_comptosing_bool +\bool_new:N \l__zrefclever_nudge_singular_bool +\bool_new:N \l__zrefclever_nudge_gender_bool +\tl_new:N \l__zrefclever_ref_gender_tl +\keys_define:nn { zref-clever / reference } + { + nudge .choice: , + nudge / true .code:n = + { \bool_set_true:N \l__zrefclever_nudge_enabled_bool } , + nudge / false .code:n = + { \bool_set_false:N \l__zrefclever_nudge_enabled_bool } , + nudge / ifdraft .code:n = + { + \ifdraft + { \bool_set_false:N \l__zrefclever_nudge_enabled_bool } + { \bool_set_true:N \l__zrefclever_nudge_enabled_bool } + } , + nudge / iffinal .code:n = + { + \ifoptionfinal + { \bool_set_true:N \l__zrefclever_nudge_enabled_bool } + { \bool_set_false:N \l__zrefclever_nudge_enabled_bool } + } , + nudge .initial:n = false , + nudge .default:n = true , + nonudge .meta:n = { nudge = false } , + nonudge .value_forbidden:n = true , + nudgeif .code:n = + { + \bool_set_false:N \l__zrefclever_nudge_multitype_bool + \bool_set_false:N \l__zrefclever_nudge_comptosing_bool + \bool_set_false:N \l__zrefclever_nudge_gender_bool + \clist_map_inline:nn {#1} + { + \str_case:nnF {##1} + { + { multitype } + { \bool_set_true:N \l__zrefclever_nudge_multitype_bool } + { comptosing } + { \bool_set_true:N \l__zrefclever_nudge_comptosing_bool } + { gender } + { \bool_set_true:N \l__zrefclever_nudge_gender_bool } + { all } + { + \bool_set_true:N \l__zrefclever_nudge_multitype_bool + \bool_set_true:N \l__zrefclever_nudge_comptosing_bool + \bool_set_true:N \l__zrefclever_nudge_gender_bool + } + } + { + \msg_warning:nnn { zref-clever } + { nudgeif-unknown-value } {##1} + } + } + } , + nudgeif .value_required:n = true , + nudgeif .initial:n = all , + sg .bool_set:N = \l__zrefclever_nudge_singular_bool , + sg .initial:n = false , + sg .default:n = true , + g .code:n = + { \msg_warning:nnn { zref-clever } { option-document-only } { g } } , + } +\AddToHook { begindocument } + { + \keys_define:nn { zref-clever / reference } + { + g .tl_set:N = \l__zrefclever_ref_gender_tl , + g .value_required:n = true , + } + } +\tl_new:N \l__zrefclever_ref_typeset_font_tl +\keys_define:nn { zref-clever / reference } + { font .tl_set:N = \l__zrefclever_ref_typeset_font_tl } +\keys_define:nn { zref-clever / reference } + { + titleref .code:n = { \RequirePackage { zref-titleref } } , + titleref .value_forbidden:n = true , + } +\AddToHook { begindocument } + { + \keys_define:nn { zref-clever / reference } + { + titleref .code:n = + { \msg_warning:nn { zref-clever } { titleref-preamble-only } } + } + } +\tl_new:N \l__zrefclever_zcref_note_tl +\keys_define:nn { zref-clever / reference } + { + note .tl_set:N = \l__zrefclever_zcref_note_tl , + note .value_required:n = true , + } +\bool_new:N \l__zrefclever_zrefcheck_available_bool +\bool_new:N \l__zrefclever_zcref_with_check_bool +\keys_define:nn { zref-clever / reference } + { + check .code:n = { \RequirePackage { zref-check } } , + check .value_forbidden:n = true , + } +\AddToHook { begindocument } + { + \__zrefclever_if_package_loaded:nTF { zref-check } + { + \bool_set_true:N \l__zrefclever_zrefcheck_available_bool + \keys_define:nn { zref-clever / reference } + { + check .code:n = + { + \bool_set_true:N \l__zrefclever_zcref_with_check_bool + \keys_set:nn { zref-check / zcheck } {#1} + } , + check .value_required:n = true , + } + } + { + \bool_set_false:N \l__zrefclever_zrefcheck_available_bool + \keys_define:nn { zref-clever / reference } + { + check .value_forbidden:n = false , + check .code:n = + { \msg_warning:nn { zref-clever } { missing-zref-check } } , + } + } + } +\prop_new:N \l__zrefclever_counter_type_prop +\keys_define:nn { zref-clever / label } + { + countertype .code:n = + { + \keyval_parse:nnn + { + \msg_warning:nnnn { zref-clever } + { key-requires-value } { countertype } + } + { + \__zrefclever_prop_put_non_empty:Nnn + \l__zrefclever_counter_type_prop + } + {#1} + } , + countertype .value_required:n = true , + countertype .initial:n = + { + subsection = section , + subsubsection = section , + subparagraph = paragraph , + enumi = item , + enumii = item , + enumiii = item , + enumiv = item , + mpfootnote = footnote , + } , + } +\seq_new:N \l__zrefclever_counter_resetters_seq +\keys_define:nn { zref-clever / label } + { + counterresetters .code:n = + { + \clist_map_inline:nn {#1} + { + \seq_if_in:NnF \l__zrefclever_counter_resetters_seq {##1} + { + \seq_put_right:Nn + \l__zrefclever_counter_resetters_seq {##1} + } + } + } , + counterresetters .initial:n = + { + part , + chapter , + section , + subsection , + subsubsection , + paragraph , + subparagraph , + }, + counterresetters .value_required:n = true , + } +\prop_new:N \l__zrefclever_counter_resetby_prop +\keys_define:nn { zref-clever / label } + { + counterresetby .code:n = + { + \keyval_parse:nnn + { + \msg_warning:nnn { zref-clever } + { key-requires-value } { counterresetby } + } + { + \__zrefclever_prop_put_non_empty:Nnn + \l__zrefclever_counter_resetby_prop + } + {#1} + } , + counterresetby .value_required:n = true , + counterresetby .initial:n = + { + enumii = enumi , + enumiii = enumii , + enumiv = enumiii , + } , + } +\tl_new:N \l__zrefclever_current_counter_tl +\keys_define:nn { zref-clever / label } + { + currentcounter .tl_set:N = \l__zrefclever_current_counter_tl , + currentcounter .value_required:n = true , + currentcounter .initial:n = \@currentcounter , + } +\bool_new:N \g__zrefclever_nocompat_bool +\seq_new:N \g__zrefclever_nocompat_modules_seq +\keys_define:nn { zref-clever / reference } + { + nocompat .code:n = + { + \tl_if_empty:nTF {#1} + { \bool_gset_true:N \g__zrefclever_nocompat_bool } + { + \clist_map_inline:nn {#1} + { + \seq_if_in:NnF \g__zrefclever_nocompat_modules_seq {##1} + { + \seq_gput_right:Nn + \g__zrefclever_nocompat_modules_seq {##1} + } + } + } + } , + } +\AddToHook { begindocument } + { + \keys_define:nn { zref-clever / reference } + { + nocompat .code:n = + { + \msg_warning:nnn { zref-clever } + { option-preamble-only } { nocompat } + } + } + } +\AtEndOfPackage + { + \AddToHook { begindocument } + { + \seq_map_inline:Nn \g__zrefclever_nocompat_modules_seq + { \msg_warning:nnn { zref-clever } { unknown-compat-module } {#1} } + } + } +\cs_new_protected:Npn \__zrefclever_compat_module:nn #1#2 + { + \AddToHook { begindocument } + { + \bool_if:NF \g__zrefclever_nocompat_bool + { \seq_if_in:NnF \g__zrefclever_nocompat_modules_seq {#1} {#2} } + \seq_gremove_all:Nn \g__zrefclever_nocompat_modules_seq {#1} + } + } +\prop_new:N \l__zrefclever_ref_options_prop +\seq_map_inline:Nn + \c__zrefclever_ref_options_reference_seq + { + \keys_define:nn { zref-clever / reference } + { + #1 .default:V = \c_novalue_tl , + #1 .code:n = + { + \tl_if_novalue:nTF {##1} + { \prop_remove:Nn \l__zrefclever_ref_options_prop {#1} } + { \prop_put:Nnn \l__zrefclever_ref_options_prop {#1} {##1} } + } , + } + } +\keys_define:nn { } + { + zref-clever / zcsetup .inherit:n = + { + zref-clever / label , + zref-clever / reference , + } + } +\ProcessKeysOptions { zref-clever / zcsetup } +\NewDocumentCommand \zcsetup { m } + { \__zrefclever_zcsetup:n {#1} } +\cs_new_protected:Npn \__zrefclever_zcsetup:n #1 + { \keys_set:nn { zref-clever / zcsetup } {#1} } +\cs_generate_variant:Nn \__zrefclever_zcsetup:n { x } +\NewDocumentCommand \zcRefTypeSetup { m m } + { + \prop_if_exist:cF { l__zrefclever_type_ #1 _options_prop } + { \prop_new:c { l__zrefclever_type_ #1 _options_prop } } + \tl_set:Nn \l__zrefclever_setup_type_tl {#1} + \keys_set:nn { zref-clever / typesetup } {#2} + } +\seq_map_inline:Nn + \c__zrefclever_ref_options_necessarily_not_type_specific_seq + { + \keys_define:nn { zref-clever / typesetup } + { + #1 .code:n = + { + \msg_warning:nnn { zref-clever } + { option-not-type-specific } {#1} + } , + } + } +\seq_map_inline:Nn + \c__zrefclever_ref_options_typesetup_seq + { + \keys_define:nn { zref-clever / typesetup } + { + #1 .default:V = \c_novalue_tl , + #1 .code:n = + { + \tl_if_novalue:nTF {##1} + { + \prop_remove:cn + { + l__zrefclever_type_ + \l__zrefclever_setup_type_tl _options_prop + } + {#1} + } + { + \prop_put:cnn + { + l__zrefclever_type_ + \l__zrefclever_setup_type_tl _options_prop + } + {#1} {##1} + } + } , + } + } +\NewDocumentCommand \zcLanguageSetup { m m } + { + \group_begin: + \prop_get:NnNTF \g__zrefclever_languages_prop {#1} + \l__zrefclever_dict_language_tl + { + \tl_clear:N \l__zrefclever_setup_type_tl + \exp_args:NNx \seq_set_from_clist:Nn + \l__zrefclever_dict_declension_seq + { + \prop_item:cn + { + g__zrefclever_dict_ + \l__zrefclever_dict_language_tl _prop + } + { declension } + } + \seq_if_empty:NTF \l__zrefclever_dict_declension_seq + { \tl_clear:N \l__zrefclever_dict_decl_case_tl } + { + \seq_get_left:NN \l__zrefclever_dict_declension_seq + \l__zrefclever_dict_decl_case_tl + } + \exp_args:NNx \seq_set_from_clist:Nn + \l__zrefclever_dict_gender_seq + { + \prop_item:cn + { + g__zrefclever_dict_ + \l__zrefclever_dict_language_tl _prop + } + { gender } + } + \keys_set:nn { zref-clever / langsetup } {#2} + } + { \msg_warning:nnn { zref-clever } { unknown-language-setup } {#1} } + \group_end: + } +\@onlypreamble \zcLanguageSetup +\cs_new_protected:Npn \__zrefclever_declare_type_transl:nnnn #1#2#3#4 + { + \prop_gput:cnn { g__zrefclever_dict_ #1 _prop } + { type- #2 - #3 } {#4} + } +\cs_generate_variant:Nn \__zrefclever_declare_type_transl:nnnn { VVnn , VVxn } +\cs_new_protected:Npn \__zrefclever_declare_default_transl:nnn #1#2#3 + { + \prop_gput:cnn { g__zrefclever_dict_ #1 _prop } + { default- #2 } {#3} + } +\cs_generate_variant:Nn \__zrefclever_declare_default_transl:nnn { Vnn } +\keys_define:nn { zref-clever / langsetup } + { + type .code:n = + { + \tl_if_empty:nTF {#1} + { \tl_clear:N \l__zrefclever_setup_type_tl } + { \tl_set:Nn \l__zrefclever_setup_type_tl {#1} } + } , + case .code:n = + { + \seq_if_empty:NTF \l__zrefclever_dict_declension_seq + { + \msg_warning:nnxx { zref-clever } { language-no-decl-setup } + { \l__zrefclever_dict_language_tl } {#1} + } + { + \seq_if_in:NnTF \l__zrefclever_dict_declension_seq {#1} + { \tl_set:Nn \l__zrefclever_dict_decl_case_tl {#1} } + { + \msg_warning:nnxx { zref-clever } { unknown-decl-case } + {#1} { \l__zrefclever_dict_language_tl } + \seq_get_left:NN \l__zrefclever_dict_declension_seq + \l__zrefclever_dict_decl_case_tl + } + } + } , + case .value_required:n = true , + gender .code:n = + { + \seq_if_empty:NTF \l__zrefclever_dict_gender_seq + { + \msg_warning:nnxxx { zref-clever } { language-no-gender } + { \l__zrefclever_dict_language_tl } { gender } {#1} + } + { + \tl_if_empty:NTF \l__zrefclever_setup_type_tl + { + \msg_warning:nnn { zref-clever } + { option-only-type-specific } { gender } + } + { + \seq_if_in:NnTF \l__zrefclever_dict_gender_seq {#1} + { + \__zrefclever_declare_type_transl:VVnn + \l__zrefclever_dict_language_tl + \l__zrefclever_setup_type_tl + { gender } {#1} + } + { + \msg_warning:nnxx { zref-clever } { gender-not-declared } + { \l__zrefclever_dict_language_tl } {#1} + } + } + } + } , + gender .value_required:n = true , + } +\seq_map_inline:Nn + \c__zrefclever_ref_options_necessarily_not_type_specific_seq + { + \keys_define:nn { zref-clever / langsetup } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l__zrefclever_setup_type_tl + { + \__zrefclever_declare_default_transl:Vnn + \l__zrefclever_dict_language_tl + {#1} {##1} + } + { + \msg_warning:nnn { zref-clever } + { option-not-type-specific } {#1} + } + } , + } + } +\seq_map_inline:Nn + \c__zrefclever_ref_options_possibly_type_specific_seq + { + \keys_define:nn { zref-clever / langsetup } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l__zrefclever_setup_type_tl + { + \__zrefclever_declare_default_transl:Vnn + \l__zrefclever_dict_language_tl + {#1} {##1} + } + { + \__zrefclever_declare_type_transl:VVnn + \l__zrefclever_dict_language_tl + \l__zrefclever_setup_type_tl + {#1} {##1} + } + } , + } + } +\seq_map_inline:Nn + \c__zrefclever_ref_options_type_names_seq + { + \keys_define:nn { zref-clever / langsetup } + { + #1 .value_required:n = true , + #1 .code:n = + { + \tl_if_empty:NTF \l__zrefclever_setup_type_tl + { + \msg_warning:nnn { zref-clever } + { option-only-type-specific } {#1} + } + { + \tl_if_empty:NTF \l__zrefclever_dict_decl_case_tl + { + \__zrefclever_declare_type_transl:VVnn + \l__zrefclever_dict_language_tl + \l__zrefclever_setup_type_tl + {#1} {##1} + } + { + \__zrefclever_declare_type_transl:VVxn + \l__zrefclever_dict_language_tl + \l__zrefclever_setup_type_tl + { \l__zrefclever_dict_decl_case_tl - #1 } {##1} + } + } + } , + } + } +\NewDocumentCommand \zcref { s O { } m } + { \zref@wrapper@babel \__zrefclever_zcref:nnn {#3} {#1} {#2} } +\cs_new_protected:Npn \__zrefclever_zcref:nnn #1#2#3 + { + \group_begin: + \keys_set:nn { zref-clever / reference } {#3} + \seq_set_from_clist:Nn \l__zrefclever_zcref_labels_seq {#1} + \bool_set:Nn \l__zrefclever_link_star_bool {#2} + \__zrefclever_provide_dictionary:x { \l__zrefclever_ref_language_tl } + \__zrefclever_process_language_options: + \bool_lazy_and:nnT + { \l__zrefclever_zrefcheck_available_bool } + { \l__zrefclever_zcref_with_check_bool } + { \zrefcheck_zcref_beg_label: } + \bool_lazy_or:nnT + { \l__zrefclever_typeset_sort_bool } + { \l__zrefclever_typeset_range_bool } + { \__zrefclever_sort_labels: } + \group_begin: + \l__zrefclever_ref_typeset_font_tl + \__zrefclever_typeset_refs: + \group_end: + \tl_if_empty:NF \l__zrefclever_zcref_note_tl + { + \__zrefclever_get_ref_string:nN { notesep } \l_tmpa_tl + \l_tmpa_tl + \l__zrefclever_zcref_note_tl + } + \bool_lazy_and:nnT + { \l__zrefclever_zrefcheck_available_bool } + { \l__zrefclever_zcref_with_check_bool } + { + \zrefcheck_zcref_end_label_maybe: + \zrefcheck_zcref_run_checks_on_labels:n + { \l__zrefclever_zcref_labels_seq } + } + \bool_if:NT \l__zrefclever_mathtools_showonlyrefs_bool + { + \__zrefclever_mathtools_showonlyrefs:n + { \l__zrefclever_zcref_labels_seq } + } + \group_end: + } +\seq_new:N \l__zrefclever_zcref_labels_seq +\bool_new:N \l__zrefclever_link_star_bool +\NewDocumentCommand \zcpageref { s O { } m } + { + \IfBooleanTF {#1} + { \zcref*[#2, ref = page] {#3} } + { \zcref [#2, ref = page] {#3} } + } +\tl_new:N \l__zrefclever_label_type_a_tl +\tl_new:N \l__zrefclever_label_type_b_tl +\tl_new:N \l__zrefclever_label_enclval_a_tl +\tl_new:N \l__zrefclever_label_enclval_b_tl +\tl_new:N \l__zrefclever_label_extdoc_a_tl +\tl_new:N \l__zrefclever_label_extdoc_b_tl +\bool_new:N \l__zrefclever_sort_decided_bool +\int_new:N \l__zrefclever_sort_prior_a_int +\int_new:N \l__zrefclever_sort_prior_b_int +\seq_new:N \l__zrefclever_label_types_seq +\cs_new_protected:Npn \__zrefclever_sort_labels: + { + \seq_clear:N \l__zrefclever_label_types_seq + \tl_if_eq:NnF \l__zrefclever_ref_property_tl { page } + { + \seq_map_function:NN \l__zrefclever_zcref_labels_seq + \__zrefclever_label_type_put_new_right:n + } + \seq_sort:Nn \l__zrefclever_zcref_labels_seq + { + \zref@ifrefundefined {##1} + { + \zref@ifrefundefined {##2} + { + % Neither label is defined. + \sort_return_same: + } + { + % The second label is defined, but the first isn't, leave the + % undefined first (to be more visible). + \sort_return_same: + } + } + { + \zref@ifrefundefined {##2} + { + % The first label is defined, but the second isn't, bring the + % second forward. + \sort_return_swapped: + } + { + % The interesting case: both labels are defined. References + % to the "default" property or to the "page" are quite + % different with regard to sorting, so we branch them here to + % specialized functions. + \tl_if_eq:NnTF \l__zrefclever_ref_property_tl { page } + { \__zrefclever_sort_page:nn {##1} {##2} } + { \__zrefclever_sort_default:nn {##1} {##2} } + } + } + } + } +\cs_new_protected:Npn \__zrefclever_label_type_put_new_right:n #1 + { + \__zrefclever_def_extract:Nnnn + \l__zrefclever_label_type_a_tl {#1} { zc@type } { \c_empty_tl } + \seq_if_in:NVF \l__zrefclever_label_types_seq + \l__zrefclever_label_type_a_tl + { + \seq_put_right:NV \l__zrefclever_label_types_seq + \l__zrefclever_label_type_a_tl + } + } +\cs_new_protected:Npn \__zrefclever_sort_default:nn #1#2 + { + \__zrefclever_def_extract:Nnnn + \l__zrefclever_label_type_a_tl {#1} { zc@type } { zc@missingtype } + \__zrefclever_def_extract:Nnnn + \l__zrefclever_label_type_b_tl {#2} { zc@type } { zc@missingtype } + + \tl_if_eq:NNTF + \l__zrefclever_label_type_a_tl + \l__zrefclever_label_type_b_tl + { \__zrefclever_sort_default_same_type:nn {#1} {#2} } + { \__zrefclever_sort_default_different_types:nn {#1} {#2} } + } +\cs_new_protected:Npn \__zrefclever_sort_default_same_type:nn #1#2 + { + \__zrefclever_def_extract:Nnnn \l__zrefclever_label_enclval_a_tl + {#1} { zc@enclval } { \c_empty_tl } + \tl_reverse:N \l__zrefclever_label_enclval_a_tl + \__zrefclever_def_extract:Nnnn \l__zrefclever_label_enclval_b_tl + {#2} { zc@enclval } { \c_empty_tl } + \tl_reverse:N \l__zrefclever_label_enclval_b_tl + \__zrefclever_def_extract:Nnnn \l__zrefclever_label_extdoc_a_tl + {#1} { externaldocument } { \c_empty_tl } + \__zrefclever_def_extract:Nnnn \l__zrefclever_label_extdoc_b_tl + {#2} { externaldocument } { \c_empty_tl } + + \bool_set_false:N \l__zrefclever_sort_decided_bool + + % First we check if there's any "external document" difference (coming + % from 'zref-xr') and, if so, sort based on that. + \tl_if_eq:NNF + \l__zrefclever_label_extdoc_a_tl + \l__zrefclever_label_extdoc_b_tl + { + \bool_if:nTF + { + \tl_if_empty_p:V \l__zrefclever_label_extdoc_a_tl && + ! \tl_if_empty_p:V \l__zrefclever_label_extdoc_b_tl + } + { + \bool_set_true:N \l__zrefclever_sort_decided_bool + \sort_return_same: + } + { + \bool_if:nTF + { + ! \tl_if_empty_p:V \l__zrefclever_label_extdoc_a_tl && + \tl_if_empty_p:V \l__zrefclever_label_extdoc_b_tl + } + { + \bool_set_true:N \l__zrefclever_sort_decided_bool + \sort_return_swapped: + } + { + \bool_set_true:N \l__zrefclever_sort_decided_bool + % Two different "external documents": last resort, sort by the + % document name itself. + \str_compare:eNeTF + { \l__zrefclever_label_extdoc_b_tl } < + { \l__zrefclever_label_extdoc_a_tl } + { \sort_return_swapped: } + { \sort_return_same: } + } + } + } + + \bool_until_do:Nn \l__zrefclever_sort_decided_bool + { + \bool_if:nTF + { + % Both are empty: neither label has any (further) "enclosing + % counters" (left). + \tl_if_empty_p:V \l__zrefclever_label_enclval_a_tl && + \tl_if_empty_p:V \l__zrefclever_label_enclval_b_tl + } + { + \bool_set_true:N \l__zrefclever_sort_decided_bool + \int_compare:nNnTF + { \__zrefclever_extract:nnn {#1} { zc@cntval } { -1 } } + > + { \__zrefclever_extract:nnn {#2} { zc@cntval } { -1 } } + { \sort_return_swapped: } + { \sort_return_same: } + } + { + \bool_if:nTF + { + % `a' is empty (and `b' is not): `b' may be nested in `a'. + \tl_if_empty_p:V \l__zrefclever_label_enclval_a_tl + } + { + \bool_set_true:N \l__zrefclever_sort_decided_bool + \int_compare:nNnTF + { \__zrefclever_extract:nnn {#1} { zc@cntval } { } } + > + { \tl_head:N \l__zrefclever_label_enclval_b_tl } + { \sort_return_swapped: } + { \sort_return_same: } + } + { + \bool_if:nTF + { + % `b' is empty (and `a' is not): `a' may be nested in `b'. + \tl_if_empty_p:V \l__zrefclever_label_enclval_b_tl + } + { + \bool_set_true:N \l__zrefclever_sort_decided_bool + \int_compare:nNnTF + { \tl_head:N \l__zrefclever_label_enclval_a_tl } + < + { \__zrefclever_extract:nnn {#2} { zc@cntval } { } } + { \sort_return_same: } + { \sort_return_swapped: } + } + { + % Neither is empty: we can compare the values of the + % current enclosing counter in the loop, if they are + % equal, we are still in the loop, if they are not, a + % sorting decision can be made directly. + \int_compare:nNnTF + { \tl_head:N \l__zrefclever_label_enclval_a_tl } + = + { \tl_head:N \l__zrefclever_label_enclval_b_tl } + { + \tl_set:Nx \l__zrefclever_label_enclval_a_tl + { \tl_tail:N \l__zrefclever_label_enclval_a_tl } + \tl_set:Nx \l__zrefclever_label_enclval_b_tl + { \tl_tail:N \l__zrefclever_label_enclval_b_tl } + } + { + \bool_set_true:N \l__zrefclever_sort_decided_bool + \int_compare:nNnTF + { \tl_head:N \l__zrefclever_label_enclval_a_tl } + > + { \tl_head:N \l__zrefclever_label_enclval_b_tl } + { \sort_return_swapped: } + { \sort_return_same: } + } + } + } + } + } + } +\cs_new_protected:Npn \__zrefclever_sort_default_different_types:nn #1#2 + { + \int_zero:N \l__zrefclever_sort_prior_a_int + \int_zero:N \l__zrefclever_sort_prior_b_int + \seq_map_indexed_inline:Nn \l__zrefclever_typesort_seq + { + \tl_if_eq:nnTF {##2} {{othertypes}} + { + \int_compare:nNnT { \l__zrefclever_sort_prior_a_int } = { 0 } + { \int_set:Nn \l__zrefclever_sort_prior_a_int { - ##1 } } + \int_compare:nNnT { \l__zrefclever_sort_prior_b_int } = { 0 } + { \int_set:Nn \l__zrefclever_sort_prior_b_int { - ##1 } } + } + { + \tl_if_eq:NnTF \l__zrefclever_label_type_a_tl {##2} + { \int_set:Nn \l__zrefclever_sort_prior_a_int { - ##1 } } + { + \tl_if_eq:NnT \l__zrefclever_label_type_b_tl {##2} + { \int_set:Nn \l__zrefclever_sort_prior_b_int { - ##1 } } + } + } + } + \bool_if:nTF + { + \int_compare_p:nNn + { \l__zrefclever_sort_prior_a_int } < + { \l__zrefclever_sort_prior_b_int } + } + { \sort_return_same: } + { + \bool_if:nTF + { + \int_compare_p:nNn + { \l__zrefclever_sort_prior_a_int } > + { \l__zrefclever_sort_prior_b_int } + } + { \sort_return_swapped: } + { + % Sort priorities are equal: the type that occurs first in + % `labels', as given by the user, is kept (or brought) forward. + \seq_map_inline:Nn \l__zrefclever_label_types_seq + { + \tl_if_eq:NnTF \l__zrefclever_label_type_a_tl {##1} + { \seq_map_break:n { \sort_return_same: } } + { + \tl_if_eq:NnT \l__zrefclever_label_type_b_tl {##1} + { \seq_map_break:n { \sort_return_swapped: } } + } + } + } + } + } +\cs_new_protected:Npn \__zrefclever_sort_page:nn #1#2 + { + \int_compare:nNnTF + { \__zrefclever_extract:nnn {#1} { abspage } { -1 } } + > + { \__zrefclever_extract:nnn {#2} { abspage } { -1 } } + { \sort_return_swapped: } + { \sort_return_same: } + } +\seq_new:N \l__zrefclever_typeset_labels_seq +\bool_new:N \l__zrefclever_typeset_last_bool +\bool_new:N \l__zrefclever_last_of_type_bool +\int_new:N \l__zrefclever_type_count_int +\int_new:N \l__zrefclever_label_count_int +\tl_new:N \l__zrefclever_label_a_tl +\tl_new:N \l__zrefclever_label_b_tl +\tl_new:N \l__zrefclever_typeset_queue_prev_tl +\tl_new:N \l__zrefclever_typeset_queue_curr_tl +\tl_new:N \l__zrefclever_type_first_label_tl +\tl_new:N \l__zrefclever_type_first_label_type_tl +\tl_new:N \l__zrefclever_type_name_tl +\bool_new:N \l__zrefclever_name_in_link_bool +\tl_new:N \l__zrefclever_name_format_tl +\tl_new:N \l__zrefclever_name_format_fallback_tl +\tl_new:N \l__zrefclever_type_name_gender_tl +\int_new:N \l__zrefclever_range_count_int +\int_new:N \l__zrefclever_range_same_count_int +\tl_new:N \l__zrefclever_range_beg_label_tl +\bool_new:N \l__zrefclever_next_maybe_range_bool +\bool_new:N \l__zrefclever_next_is_same_bool +\tl_new:N \l__zrefclever_tpairsep_tl +\tl_new:N \l__zrefclever_tlistsep_tl +\tl_new:N \l__zrefclever_tlastsep_tl +\tl_new:N \l__zrefclever_namesep_tl +\tl_new:N \l__zrefclever_pairsep_tl +\tl_new:N \l__zrefclever_listsep_tl +\tl_new:N \l__zrefclever_lastsep_tl +\tl_new:N \l__zrefclever_rangesep_tl +\tl_new:N \l__zrefclever_refpre_tl +\tl_new:N \l__zrefclever_refpos_tl +\tl_new:N \l__zrefclever_namefont_tl +\tl_new:N \l__zrefclever_reffont_tl +\bool_new:N \l__zrefclever_verbose_testing_bool +\cs_new_protected:Npn \__zrefclever_typeset_refs: + { + \seq_set_eq:NN \l__zrefclever_typeset_labels_seq + \l__zrefclever_zcref_labels_seq + \tl_clear:N \l__zrefclever_typeset_queue_prev_tl + \tl_clear:N \l__zrefclever_typeset_queue_curr_tl + \tl_clear:N \l__zrefclever_type_first_label_tl + \tl_clear:N \l__zrefclever_type_first_label_type_tl + \tl_clear:N \l__zrefclever_range_beg_label_tl + \int_zero:N \l__zrefclever_label_count_int + \int_zero:N \l__zrefclever_type_count_int + \int_zero:N \l__zrefclever_range_count_int + \int_zero:N \l__zrefclever_range_same_count_int + + % Get type block options (not type-specific). + \__zrefclever_get_ref_string:nN { tpairsep } + \l__zrefclever_tpairsep_tl + \__zrefclever_get_ref_string:nN { tlistsep } + \l__zrefclever_tlistsep_tl + \__zrefclever_get_ref_string:nN { tlastsep } + \l__zrefclever_tlastsep_tl + + % Process label stack. + \bool_set_false:N \l__zrefclever_typeset_last_bool + \bool_until_do:Nn \l__zrefclever_typeset_last_bool + { + \seq_pop_left:NN \l__zrefclever_typeset_labels_seq + \l__zrefclever_label_a_tl + \seq_if_empty:NTF \l__zrefclever_typeset_labels_seq + { + \tl_clear:N \l__zrefclever_label_b_tl + \bool_set_true:N \l__zrefclever_typeset_last_bool + } + { + \seq_get_left:NN \l__zrefclever_typeset_labels_seq + \l__zrefclever_label_b_tl + } + + \tl_if_eq:NnTF \l__zrefclever_ref_property_tl { page } + { + \tl_set:Nn \l__zrefclever_label_type_a_tl { page } + \tl_set:Nn \l__zrefclever_label_type_b_tl { page } + } + { + \__zrefclever_def_extract:NVnn \l__zrefclever_label_type_a_tl + \l__zrefclever_label_a_tl { zc@type } { zc@missingtype } + \__zrefclever_def_extract:NVnn \l__zrefclever_label_type_b_tl + \l__zrefclever_label_b_tl { zc@type } { zc@missingtype } + } + + % First, we establish whether the "current label" (i.e. `a') is the + % last one of its type. This can happen because the "next label" + % (i.e. `b') is of a different type (or different definition status), + % or because we are at the end of the list. + \bool_if:NTF \l__zrefclever_typeset_last_bool + { \bool_set_true:N \l__zrefclever_last_of_type_bool } + { + \zref@ifrefundefined { \l__zrefclever_label_a_tl } + { + \zref@ifrefundefined { \l__zrefclever_label_b_tl } + { \bool_set_false:N \l__zrefclever_last_of_type_bool } + { \bool_set_true:N \l__zrefclever_last_of_type_bool } + } + { + \zref@ifrefundefined { \l__zrefclever_label_b_tl } + { \bool_set_true:N \l__zrefclever_last_of_type_bool } + { + % Neither is undefined, we must check the types. + \tl_if_eq:NNTF + \l__zrefclever_label_type_a_tl + \l__zrefclever_label_type_b_tl + { \bool_set_false:N \l__zrefclever_last_of_type_bool } + { \bool_set_true:N \l__zrefclever_last_of_type_bool } + } + } + } + + % Handle warnings in case of reference or type undefined. + % Test: 'zc-typeset01.lvt': "Typeset refs: warn ref undefined" + \zref@refused { \l__zrefclever_label_a_tl } + % Test: 'zc-typeset01.lvt': "Typeset refs: warn missing type" + \zref@ifrefundefined { \l__zrefclever_label_a_tl } + {} + { + \tl_if_eq:NnT \l__zrefclever_label_type_a_tl { zc@missingtype } + { + \msg_warning:nnx { zref-clever } { missing-type } + { \l__zrefclever_label_a_tl } + } + \zref@ifrefcontainsprop + { \l__zrefclever_label_a_tl } + { \l__zrefclever_ref_property_tl } + { } + { + \msg_warning:nnxx { zref-clever } { missing-property } + { \l__zrefclever_ref_property_tl } + { \l__zrefclever_label_a_tl } + } + } + + % Get type-specific separators, refpre/pos and font options, once per + % type. + \int_compare:nNnT { \l__zrefclever_label_count_int } = { 0 } + { + \__zrefclever_get_ref_string:nN { namesep } + \l__zrefclever_namesep_tl + \__zrefclever_get_ref_string:nN { pairsep } + \l__zrefclever_pairsep_tl + \__zrefclever_get_ref_string:nN { listsep } + \l__zrefclever_listsep_tl + \__zrefclever_get_ref_string:nN { lastsep } + \l__zrefclever_lastsep_tl + \__zrefclever_get_ref_string:nN { rangesep } + \l__zrefclever_rangesep_tl + \__zrefclever_get_ref_string:nN { refpre } + \l__zrefclever_refpre_tl + \__zrefclever_get_ref_string:nN { refpos } + \l__zrefclever_refpos_tl + \__zrefclever_get_ref_font:nN { namefont } + \l__zrefclever_namefont_tl + \__zrefclever_get_ref_font:nN { reffont } + \l__zrefclever_reffont_tl + } + + % Here we send this to a couple of auxiliary functions. + \bool_if:NTF \l__zrefclever_last_of_type_bool + % There exists no next label of the same type as the current. + { \__zrefclever_typeset_refs_last_of_type: } + % There exists a next label of the same type as the current. + { \__zrefclever_typeset_refs_not_last_of_type: } + } + } +\cs_new_protected:Npn \__zrefclever_typeset_refs_last_of_type: + { + % Process the current label to the current queue. + \int_case:nnF { \l__zrefclever_label_count_int } + { + % It is the last label of its type, but also the first one, and that's + % what matters here: just store it. + % Test: 'zc-typeset01.lvt': "Last of type: single" + { 0 } + { + \tl_set:NV \l__zrefclever_type_first_label_tl + \l__zrefclever_label_a_tl + \tl_set:NV \l__zrefclever_type_first_label_type_tl + \l__zrefclever_label_type_a_tl + } + + % The last is the second: we have a pair (if not repeated). + % Test: 'zc-typeset01.lvt': "Last of type: pair" + { 1 } + { + \int_compare:nNnF { \l__zrefclever_range_same_count_int } = { 1 } + { + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + \exp_not:V \l__zrefclever_pairsep_tl + \__zrefclever_get_ref:V \l__zrefclever_label_a_tl + } + } + } + } + % Last is third or more of its type: without repetition, we'd have the + % last element on a list, but control for possible repetition. + { + \int_case:nnF { \l__zrefclever_range_count_int } + { + % There was no range going on. + % Test: 'zc-typeset01.lvt': "Last of type: not range" + { 0 } + { + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + \exp_not:V \l__zrefclever_lastsep_tl + \__zrefclever_get_ref:V \l__zrefclever_label_a_tl + } + } + % Last in the range is also the second in it. + % Test: 'zc-typeset01.lvt': "Last of type: pair in sequence" + { 1 } + { + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + % We know `range_beg_label' is not empty, since this is the + % second element in the range, but the third or more in the + % type list. + \exp_not:V \l__zrefclever_listsep_tl + \__zrefclever_get_ref:V \l__zrefclever_range_beg_label_tl + \int_compare:nNnF + { \l__zrefclever_range_same_count_int } = { 1 } + { + \exp_not:V \l__zrefclever_lastsep_tl + \__zrefclever_get_ref:V \l__zrefclever_label_a_tl + } + } + } + } + % Last in the range is third or more in it. + { + \int_case:nnF + { + \l__zrefclever_range_count_int - + \l__zrefclever_range_same_count_int + } + { + % Repetition, not a range. + % Test: 'zc-typeset01.lvt': "Last of type: range to one" + { 0 } + { + % If `range_beg_label' is empty, it means it was also the + % first of the type, and hence was already handled. + \tl_if_empty:VF \l__zrefclever_range_beg_label_tl + { + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + \exp_not:V \l__zrefclever_lastsep_tl + \__zrefclever_get_ref:V + \l__zrefclever_range_beg_label_tl + } + } + } + % A `range', but with no skipped value, treat as list. + % Test: 'zc-typeset01.lvt': "Last of type: range to pair" + { 1 } + { + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + % Ditto. + \tl_if_empty:VF \l__zrefclever_range_beg_label_tl + { + \exp_not:V \l__zrefclever_listsep_tl + \__zrefclever_get_ref:V + \l__zrefclever_range_beg_label_tl + } + \exp_not:V \l__zrefclever_lastsep_tl + \__zrefclever_get_ref:V \l__zrefclever_label_a_tl + } + } + } + { + % An actual range. + % Test: 'zc-typeset01.lvt': "Last of type: range" + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + % Ditto. + \tl_if_empty:VF \l__zrefclever_range_beg_label_tl + { + \exp_not:V \l__zrefclever_lastsep_tl + \__zrefclever_get_ref:V + \l__zrefclever_range_beg_label_tl + } + \exp_not:V \l__zrefclever_rangesep_tl + \__zrefclever_get_ref:V \l__zrefclever_label_a_tl + } + } + } + } + + % Handle "range" option. The idea is simple: if the queue is not empty, + % we replace it with the end of the range (or pair). We can still + % retrieve the end of the range from `label_a' since we know to be + % processing the last label of its type at this point. + \bool_if:NT \l__zrefclever_typeset_range_bool + { + \tl_if_empty:NTF \l__zrefclever_typeset_queue_curr_tl + { + \zref@ifrefundefined { \l__zrefclever_type_first_label_tl } + { } + { + \msg_warning:nnx { zref-clever } { single-element-range } + { \l__zrefclever_type_first_label_type_tl } + } + } + { + \bool_set_false:N \l__zrefclever_next_maybe_range_bool + \zref@ifrefundefined { \l__zrefclever_type_first_label_tl } + { } + { + \__zrefclever_labels_in_sequence:nn + { \l__zrefclever_type_first_label_tl } + { \l__zrefclever_label_a_tl } + } + % Test: 'zc-typeset01.lvt': "Last of type: option range" + % Test: 'zc-typeset01.lvt': "Last of type: option range to pair" + \tl_set:Nx \l__zrefclever_typeset_queue_curr_tl + { + \bool_if:NTF \l__zrefclever_next_maybe_range_bool + { \exp_not:V \l__zrefclever_pairsep_tl } + { \exp_not:V \l__zrefclever_rangesep_tl } + \__zrefclever_get_ref:V \l__zrefclever_label_a_tl + } + } + } + + % Now that the type block is finished, we can add the name and the first + % ref to the queue. Also, if "typeset" option is not "both", handle it + % here as well. + \__zrefclever_type_name_setup: + \bool_if:nTF + { \l__zrefclever_typeset_ref_bool && \l__zrefclever_typeset_name_bool } + { + \tl_put_left:Nx \l__zrefclever_typeset_queue_curr_tl + { \__zrefclever_get_ref_first: } + } + { + \bool_if:NTF \l__zrefclever_typeset_ref_bool + { + % Test: 'zc-typeset01.lvt': "Last of type: option typeset ref" + \tl_put_left:Nx \l__zrefclever_typeset_queue_curr_tl + { \__zrefclever_get_ref:V \l__zrefclever_type_first_label_tl } + } + { + \bool_if:NTF \l__zrefclever_typeset_name_bool + { + % Test: 'zc-typeset01.lvt': "Last of type: option typeset name" + \tl_set:Nx \l__zrefclever_typeset_queue_curr_tl + { + \bool_if:NTF \l__zrefclever_name_in_link_bool + { + \exp_not:N \group_begin: + \exp_not:V \l__zrefclever_namefont_tl + % It's two '@s', but escaped for DocStrip. + \exp_not:N \hyper@@link + { + \__zrefclever_extract_url_unexp:V + \l__zrefclever_type_first_label_tl + } + { + \__zrefclever_extract_unexp:Vnn + \l__zrefclever_type_first_label_tl + { anchor } { } + } + { \exp_not:V \l__zrefclever_type_name_tl } + \exp_not:N \group_end: + } + { + \exp_not:N \group_begin: + \exp_not:V \l__zrefclever_namefont_tl + \exp_not:V \l__zrefclever_type_name_tl + \exp_not:N \group_end: + } + } + } + { + % Logically, this case would correspond to "typeset=none", but + % it should not occur, given that the options are set up to + % typeset either "ref" or "name". Still, leave here a + % sensible fallback, equal to the behavior of "both". + % Test: 'zc-typeset01.lvt': "Last of type: option typeset none" + \tl_put_left:Nx \l__zrefclever_typeset_queue_curr_tl + { \__zrefclever_get_ref_first: } + } + } + } + + % Typeset the previous type block, if there is one. + \int_compare:nNnT { \l__zrefclever_type_count_int } > { 0 } + { + \int_compare:nNnT { \l__zrefclever_type_count_int } > { 1 } + { \l__zrefclever_tlistsep_tl } + \l__zrefclever_typeset_queue_prev_tl + } + + % Extra log for testing. + \bool_if:NT \l__zrefclever_verbose_testing_bool + { \tl_show:N \l__zrefclever_typeset_queue_curr_tl } + + % Wrap up loop, or prepare for next iteration. + \bool_if:NTF \l__zrefclever_typeset_last_bool + { + % We are finishing, typeset the current queue. + \int_case:nnF { \l__zrefclever_type_count_int } + { + % Single type. + % Test: 'zc-typeset01.lvt': "Last of type: single type" + { 0 } + { \l__zrefclever_typeset_queue_curr_tl } + % Pair of types. + % Test: 'zc-typeset01.lvt': "Last of type: pair of types" + { 1 } + { + \l__zrefclever_tpairsep_tl + \l__zrefclever_typeset_queue_curr_tl + } + } + { + % Last in list of types. + % Test: 'zc-typeset01.lvt': "Last of type: list of types" + \l__zrefclever_tlastsep_tl + \l__zrefclever_typeset_queue_curr_tl + } + % And nudge in case of multitype reference. + \bool_lazy_all:nT + { + { \l__zrefclever_nudge_enabled_bool } + { \l__zrefclever_nudge_multitype_bool } + { \int_compare_p:nNn { \l__zrefclever_type_count_int } > { 0 } } + } + { \msg_warning:nn { zref-clever } { nudge-multitype } } + } + { + % There are further labels, set variables for next iteration. + \tl_set_eq:NN \l__zrefclever_typeset_queue_prev_tl + \l__zrefclever_typeset_queue_curr_tl + \tl_clear:N \l__zrefclever_typeset_queue_curr_tl + \tl_clear:N \l__zrefclever_type_first_label_tl + \tl_clear:N \l__zrefclever_type_first_label_type_tl + \tl_clear:N \l__zrefclever_range_beg_label_tl + \int_zero:N \l__zrefclever_label_count_int + \int_incr:N \l__zrefclever_type_count_int + \int_zero:N \l__zrefclever_range_count_int + \int_zero:N \l__zrefclever_range_same_count_int + } + } +\cs_new_protected:Npn \__zrefclever_typeset_refs_not_last_of_type: + { + % Signal if next label may form a range with the current one (only + % considered if compression is enabled in the first place). + \bool_set_false:N \l__zrefclever_next_maybe_range_bool + \bool_set_false:N \l__zrefclever_next_is_same_bool + \bool_if:NT \l__zrefclever_typeset_compress_bool + { + \zref@ifrefundefined { \l__zrefclever_label_a_tl } + { } + { + \__zrefclever_labels_in_sequence:nn + { \l__zrefclever_label_a_tl } { \l__zrefclever_label_b_tl } + } + } + + % Process the current label to the current queue. + \int_compare:nNnTF { \l__zrefclever_label_count_int } = { 0 } + { + % Current label is the first of its type (also not the last, but it + % doesn't matter here): just store the label. + \tl_set:NV \l__zrefclever_type_first_label_tl + \l__zrefclever_label_a_tl + \tl_set:NV \l__zrefclever_type_first_label_type_tl + \l__zrefclever_label_type_a_tl + + % If the next label may be part of a range, we set `range_beg_label' + % to "empty" (we deal with it as the "first", and must do it there, to + % handle hyperlinking), but also step the range counters. + % Test: 'zc-typeset01.lvt': "Not last of type: first is range" + \bool_if:NT \l__zrefclever_next_maybe_range_bool + { + \tl_clear:N \l__zrefclever_range_beg_label_tl + \int_incr:N \l__zrefclever_range_count_int + \bool_if:NT \l__zrefclever_next_is_same_bool + { \int_incr:N \l__zrefclever_range_same_count_int } + } + } + { + % Current label is neither the first (nor the last) of its type. + \bool_if:NTF \l__zrefclever_next_maybe_range_bool + { + % Starting, or continuing a range. + \int_compare:nNnTF + { \l__zrefclever_range_count_int } = { 0 } + { + % There was no range going, we are starting one. + \tl_set:NV \l__zrefclever_range_beg_label_tl + \l__zrefclever_label_a_tl + \int_incr:N \l__zrefclever_range_count_int + \bool_if:NT \l__zrefclever_next_is_same_bool + { \int_incr:N \l__zrefclever_range_same_count_int } + } + { + % Second or more in the range, but not the last. + \int_incr:N \l__zrefclever_range_count_int + \bool_if:NT \l__zrefclever_next_is_same_bool + { \int_incr:N \l__zrefclever_range_same_count_int } + } + } + { + % Next element is not in sequence: there was no range, or we are + % closing one. + \int_case:nnF { \l__zrefclever_range_count_int } + { + % There was no range going on. + % Test: 'zc-typeset01.lvt': "Not last of type: no range" + { 0 } + { + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + \exp_not:V \l__zrefclever_listsep_tl + \__zrefclever_get_ref:V \l__zrefclever_label_a_tl + } + } + % Last is second in the range: if `range_same_count' is also + % `1', it's a repetition (drop it), otherwise, it's a "pair + % within a list", treat as list. + % Test: 'zc-typeset01.lvt': "Not last of type: range pair to one" + % Test: 'zc-typeset01.lvt': "Not last of type: range pair" + { 1 } + { + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + \tl_if_empty:VF \l__zrefclever_range_beg_label_tl + { + \exp_not:V \l__zrefclever_listsep_tl + \__zrefclever_get_ref:V + \l__zrefclever_range_beg_label_tl + } + \int_compare:nNnF + { \l__zrefclever_range_same_count_int } = { 1 } + { + \exp_not:V \l__zrefclever_listsep_tl + \__zrefclever_get_ref:V + \l__zrefclever_label_a_tl + } + } + } + } + { + % Last is third or more in the range: if `range_count' and + % `range_same_count' are the same, its a repetition (drop it), + % if they differ by `1', its a list, if they differ by more, + % it is a real range. + \int_case:nnF + { + \l__zrefclever_range_count_int - + \l__zrefclever_range_same_count_int + } + { + % Test: 'zc-typeset01.lvt': "Not last of type: range to one" + { 0 } + { + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + \tl_if_empty:VF \l__zrefclever_range_beg_label_tl + { + \exp_not:V \l__zrefclever_listsep_tl + \__zrefclever_get_ref:V + \l__zrefclever_range_beg_label_tl + } + } + } + % Test: 'zc-typeset01.lvt': "Not last of type: range to pair" + { 1 } + { + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + \tl_if_empty:VF \l__zrefclever_range_beg_label_tl + { + \exp_not:V \l__zrefclever_listsep_tl + \__zrefclever_get_ref:V + \l__zrefclever_range_beg_label_tl + } + \exp_not:V \l__zrefclever_listsep_tl + \__zrefclever_get_ref:V \l__zrefclever_label_a_tl + } + } + } + { + % Test: 'zc-typeset01.lvt': "Not last of type: range" + \tl_put_right:Nx \l__zrefclever_typeset_queue_curr_tl + { + \tl_if_empty:VF \l__zrefclever_range_beg_label_tl + { + \exp_not:V \l__zrefclever_listsep_tl + \__zrefclever_get_ref:V + \l__zrefclever_range_beg_label_tl + } + \exp_not:V \l__zrefclever_rangesep_tl + \__zrefclever_get_ref:V \l__zrefclever_label_a_tl + } + } + } + % Reset counters. + \int_zero:N \l__zrefclever_range_count_int + \int_zero:N \l__zrefclever_range_same_count_int + } + } + % Step label counter for next iteration. + \int_incr:N \l__zrefclever_label_count_int + } +\cs_new_protected:Npn \__zrefclever_ref_default: + { \zref@default } +\cs_new_protected:Npn \__zrefclever_name_default: + { \zref@default } +\cs_new:Npn \__zrefclever_get_ref:n #1 + { + \zref@ifrefcontainsprop {#1} { \l__zrefclever_ref_property_tl } + { + \bool_if:nTF + { + \l__zrefclever_use_hyperref_bool && + ! \l__zrefclever_link_star_bool + } + { + \bool_if:NF \l__zrefclever_preposinlink_bool + { \exp_not:V \l__zrefclever_refpre_tl } + % It's two `@s', but escaped for DocStrip. + \exp_not:N \hyper@@link + { \__zrefclever_extract_url_unexp:n {#1} } + { \__zrefclever_extract_unexp:nnn {#1} { anchor } { } } + { + \bool_if:NT \l__zrefclever_preposinlink_bool + { \exp_not:V \l__zrefclever_refpre_tl } + \exp_not:N \group_begin: + \exp_not:V \l__zrefclever_reffont_tl + \__zrefclever_extract_unexp:nvn {#1} + { l__zrefclever_ref_property_tl } { } + \exp_not:N \group_end: + \bool_if:NT \l__zrefclever_preposinlink_bool + { \exp_not:V \l__zrefclever_refpos_tl } + } + \bool_if:NF \l__zrefclever_preposinlink_bool + { \exp_not:V \l__zrefclever_refpos_tl } + } + { + \exp_not:V \l__zrefclever_refpre_tl + \exp_not:N \group_begin: + \exp_not:V \l__zrefclever_reffont_tl + \__zrefclever_extract_unexp:nvn {#1} + { l__zrefclever_ref_property_tl } { } + \exp_not:N \group_end: + \exp_not:V \l__zrefclever_refpos_tl + } + } + { \__zrefclever_ref_default: } + } +\cs_generate_variant:Nn \__zrefclever_get_ref:n { V } +\cs_new:Npn \__zrefclever_get_ref_first: + { + \zref@ifrefundefined { \l__zrefclever_type_first_label_tl } + { \__zrefclever_ref_default: } + { + \bool_if:NTF \l__zrefclever_name_in_link_bool + { + \zref@ifrefcontainsprop + { \l__zrefclever_type_first_label_tl } + { \l__zrefclever_ref_property_tl } + { + % It's two `@s', but escaped for DocStrip. + \exp_not:N \hyper@@link + { + \__zrefclever_extract_url_unexp:V + \l__zrefclever_type_first_label_tl + } + { + \__zrefclever_extract_unexp:Vnn + \l__zrefclever_type_first_label_tl { anchor } { } + } + { + \exp_not:N \group_begin: + \exp_not:V \l__zrefclever_namefont_tl + \exp_not:V \l__zrefclever_type_name_tl + \exp_not:N \group_end: + \exp_not:V \l__zrefclever_namesep_tl + \exp_not:V \l__zrefclever_refpre_tl + \exp_not:N \group_begin: + \exp_not:V \l__zrefclever_reffont_tl + \__zrefclever_extract_unexp:Vvn + \l__zrefclever_type_first_label_tl + { l__zrefclever_ref_property_tl } { } + \exp_not:N \group_end: + \bool_if:NT \l__zrefclever_preposinlink_bool + { \exp_not:V \l__zrefclever_refpos_tl } + } + \bool_if:NF \l__zrefclever_preposinlink_bool + { \exp_not:V \l__zrefclever_refpos_tl } + } + { + \exp_not:N \group_begin: + \exp_not:V \l__zrefclever_namefont_tl + \exp_not:V \l__zrefclever_type_name_tl + \exp_not:N \group_end: + \exp_not:V \l__zrefclever_namesep_tl + \__zrefclever_ref_default: + } + } + { + \tl_if_empty:NTF \l__zrefclever_type_name_tl + { + \__zrefclever_name_default: + \exp_not:V \l__zrefclever_namesep_tl + } + { + \exp_not:N \group_begin: + \exp_not:V \l__zrefclever_namefont_tl + \exp_not:V \l__zrefclever_type_name_tl + \exp_not:N \group_end: + \exp_not:V \l__zrefclever_namesep_tl + } + \zref@ifrefcontainsprop + { \l__zrefclever_type_first_label_tl } + { \l__zrefclever_ref_property_tl } + { + \bool_if:nTF + { + \l__zrefclever_use_hyperref_bool && + ! \l__zrefclever_link_star_bool + } + { + \bool_if:NF \l__zrefclever_preposinlink_bool + { \exp_not:V \l__zrefclever_refpre_tl } + % It's two '@s', but escaped for DocStrip. + \exp_not:N \hyper@@link + { + \__zrefclever_extract_url_unexp:V + \l__zrefclever_type_first_label_tl + } + { + \__zrefclever_extract_unexp:Vnn + \l__zrefclever_type_first_label_tl { anchor } { } + } + { + \bool_if:NT \l__zrefclever_preposinlink_bool + { \exp_not:V \l__zrefclever_refpre_tl } + \exp_not:N \group_begin: + \exp_not:V \l__zrefclever_reffont_tl + \__zrefclever_extract_unexp:Vvn + \l__zrefclever_type_first_label_tl + { l__zrefclever_ref_property_tl } { } + \exp_not:N \group_end: + \bool_if:NT \l__zrefclever_preposinlink_bool + { \exp_not:V \l__zrefclever_refpos_tl } + } + \bool_if:NF \l__zrefclever_preposinlink_bool + { \exp_not:V \l__zrefclever_refpos_tl } + } + { + \exp_not:V \l__zrefclever_refpre_tl + \exp_not:N \group_begin: + \exp_not:V \l__zrefclever_reffont_tl + \__zrefclever_extract_unexp:Vvn + \l__zrefclever_type_first_label_tl + { l__zrefclever_ref_property_tl } { } + \exp_not:N \group_end: + \exp_not:V \l__zrefclever_refpos_tl + } + } + { \__zrefclever_ref_default: } + } + } + } +\cs_new_protected:Npn \__zrefclever_type_name_setup: + { + \zref@ifrefundefined { \l__zrefclever_type_first_label_tl } + { \tl_clear:N \l__zrefclever_type_name_tl } + { + \tl_if_eq:NnTF + \l__zrefclever_type_first_label_type_tl { zc@missingtype } + { \tl_clear:N \l__zrefclever_type_name_tl } + { + % Determine whether we should use capitalization, abbreviation, + % and plural. + \bool_lazy_or:nnTF + { \l__zrefclever_capitalize_bool } + { + \l__zrefclever_capitalize_first_bool && + \int_compare_p:nNn { \l__zrefclever_type_count_int } = { 0 } + } + { \tl_set:Nn \l__zrefclever_name_format_tl {Name} } + { \tl_set:Nn \l__zrefclever_name_format_tl {name} } + % If the queue is empty, we have a singular, otherwise, plural. + \tl_if_empty:NTF \l__zrefclever_typeset_queue_curr_tl + { \tl_put_right:Nn \l__zrefclever_name_format_tl { -sg } } + { \tl_put_right:Nn \l__zrefclever_name_format_tl { -pl } } + \bool_lazy_and:nnTF + { \l__zrefclever_abbrev_bool } + { + ! \int_compare_p:nNn + { \l__zrefclever_type_count_int } = { 0 } || + ! \l__zrefclever_noabbrev_first_bool + } + { + \tl_set:NV \l__zrefclever_name_format_fallback_tl + \l__zrefclever_name_format_tl + \tl_put_right:Nn \l__zrefclever_name_format_tl { -ab } + } + { \tl_clear:N \l__zrefclever_name_format_fallback_tl } + + % Handle number and gender nudges. + \bool_if:NT \l__zrefclever_nudge_enabled_bool + { + \bool_if:NTF \l__zrefclever_nudge_singular_bool + { + \tl_if_empty:NF \l__zrefclever_typeset_queue_curr_tl + { + \msg_warning:nnx { zref-clever } + { nudge-plural-when-sg } + { \l__zrefclever_type_first_label_type_tl } + } + } + { + \bool_lazy_all:nT + { + { \l__zrefclever_nudge_comptosing_bool } + { \tl_if_empty_p:N \l__zrefclever_typeset_queue_curr_tl } + { + \int_compare_p:nNn + { \l__zrefclever_label_count_int } > { 0 } + } + } + { + \msg_warning:nnx { zref-clever } + { nudge-comptosing } + { \l__zrefclever_type_first_label_type_tl } + } + } + \bool_lazy_and:nnT + { \l__zrefclever_nudge_gender_bool } + { ! \tl_if_empty_p:N \l__zrefclever_ref_gender_tl } + { + \__zrefclever_get_type_transl:xxnNF + { \l__zrefclever_ref_language_tl } + { \l__zrefclever_type_first_label_type_tl } + { gender } + \l__zrefclever_type_name_gender_tl + { \tl_clear:N \l__zrefclever_type_name_gender_tl } + \tl_if_eq:NNF + \l__zrefclever_ref_gender_tl + \l__zrefclever_type_name_gender_tl + { + \tl_if_empty:NTF \l__zrefclever_type_name_gender_tl + { + \msg_warning:nnxxx { zref-clever } + { nudge-gender-not-declared-for-type } + { \l__zrefclever_ref_gender_tl } + { \l__zrefclever_type_first_label_type_tl } + { \l__zrefclever_ref_language_tl } + } + { + \msg_warning:nnxxxx { zref-clever } + { nudge-gender-mismatch } + { \l__zrefclever_type_first_label_type_tl } + { \l__zrefclever_ref_gender_tl } + { \l__zrefclever_type_name_gender_tl } + { \l__zrefclever_ref_language_tl } + } + } + } + } + + \tl_if_empty:NTF \l__zrefclever_name_format_fallback_tl + { + \prop_get:cVNF + { + l__zrefclever_type_ + \l__zrefclever_type_first_label_type_tl _options_prop + } + \l__zrefclever_name_format_tl + \l__zrefclever_type_name_tl + { + \tl_if_empty:NF \l__zrefclever_ref_decl_case_tl + { + \tl_put_left:Nn \l__zrefclever_name_format_tl { - } + \tl_put_left:NV \l__zrefclever_name_format_tl + \l__zrefclever_ref_decl_case_tl + } + \__zrefclever_get_type_transl:xxxNF + { \l__zrefclever_ref_language_tl } + { \l__zrefclever_type_first_label_type_tl } + { \l__zrefclever_name_format_tl } + \l__zrefclever_type_name_tl + { + \tl_clear:N \l__zrefclever_type_name_tl + \msg_warning:nnxx { zref-clever } { missing-name } + { \l__zrefclever_name_format_tl } + { \l__zrefclever_type_first_label_type_tl } + } + } + } + { + \prop_get:cVNF + { + l__zrefclever_type_ + \l__zrefclever_type_first_label_type_tl _options_prop + } + \l__zrefclever_name_format_tl + \l__zrefclever_type_name_tl + { + \prop_get:cVNF + { + l__zrefclever_type_ + \l__zrefclever_type_first_label_type_tl _options_prop + } + \l__zrefclever_name_format_fallback_tl + \l__zrefclever_type_name_tl + { + \tl_if_empty:NF \l__zrefclever_ref_decl_case_tl + { + \tl_put_left:Nn + \l__zrefclever_name_format_tl { - } + \tl_put_left:NV \l__zrefclever_name_format_tl + \l__zrefclever_ref_decl_case_tl + \tl_put_left:Nn + \l__zrefclever_name_format_fallback_tl { - } + \tl_put_left:NV + \l__zrefclever_name_format_fallback_tl + \l__zrefclever_ref_decl_case_tl + } + \__zrefclever_get_type_transl:xxxNF + { \l__zrefclever_ref_language_tl } + { \l__zrefclever_type_first_label_type_tl } + { \l__zrefclever_name_format_tl } + \l__zrefclever_type_name_tl + { + \__zrefclever_get_type_transl:xxxNF + { \l__zrefclever_ref_language_tl } + { \l__zrefclever_type_first_label_type_tl } + { \l__zrefclever_name_format_fallback_tl } + \l__zrefclever_type_name_tl + { + \tl_clear:N \l__zrefclever_type_name_tl + \msg_warning:nnxx { zref-clever } + { missing-name } + { \l__zrefclever_name_format_tl } + { \l__zrefclever_type_first_label_type_tl } + } + } + } + } + } + } + } + + % Signal whether the type name is to be included in the hyperlink or not. + \bool_lazy_any:nTF + { + { ! \l__zrefclever_use_hyperref_bool } + { \l__zrefclever_link_star_bool } + { \tl_if_empty_p:N \l__zrefclever_type_name_tl } + { \str_if_eq_p:Vn \l__zrefclever_nameinlink_str { false } } + } + { \bool_set_false:N \l__zrefclever_name_in_link_bool } + { + \bool_lazy_any:nTF + { + { \str_if_eq_p:Vn \l__zrefclever_nameinlink_str { true } } + { + \str_if_eq_p:Vn \l__zrefclever_nameinlink_str { tsingle } && + \tl_if_empty_p:N \l__zrefclever_typeset_queue_curr_tl + } + { + \str_if_eq_p:Vn \l__zrefclever_nameinlink_str { single } && + \tl_if_empty_p:N \l__zrefclever_typeset_queue_curr_tl && + \l__zrefclever_typeset_last_bool && + \int_compare_p:nNn { \l__zrefclever_type_count_int } = { 0 } + } + } + { \bool_set_true:N \l__zrefclever_name_in_link_bool } + { \bool_set_false:N \l__zrefclever_name_in_link_bool } + } + } +\cs_new:Npn \__zrefclever_extract_url_unexp:n #1 + { + \zref@ifpropundefined { urluse } + { \__zrefclever_extract_unexp:nnn {#1} { url } { \c_empty_tl } } + { + \zref@ifrefcontainsprop {#1} { urluse } + { \__zrefclever_extract_unexp:nnn {#1} { urluse } { \c_empty_tl } } + { \__zrefclever_extract_unexp:nnn {#1} { url } { \c_empty_tl } } + } + } +\cs_generate_variant:Nn \__zrefclever_extract_url_unexp:n { V } +\cs_new_protected:Npn \__zrefclever_labels_in_sequence:nn #1#2 + { + \__zrefclever_def_extract:Nnnn \l__zrefclever_label_extdoc_a_tl + {#1} { externaldocument } { \c_empty_tl } + \__zrefclever_def_extract:Nnnn \l__zrefclever_label_extdoc_b_tl + {#2} { externaldocument } { \c_empty_tl } + + \tl_if_eq:NNT + \l__zrefclever_label_extdoc_a_tl + \l__zrefclever_label_extdoc_b_tl + { + \tl_if_eq:NnTF \l__zrefclever_ref_property_tl { page } + { + \exp_args:Nxx \tl_if_eq:nnT + { \__zrefclever_extract_unexp:nnn {#1} { zc@pgfmt } { } } + { \__zrefclever_extract_unexp:nnn {#2} { zc@pgfmt } { } } + { + \int_compare:nNnTF + { \__zrefclever_extract:nnn {#1} { zc@pgval } { -2 } + 1 } + = + { \__zrefclever_extract:nnn {#2} { zc@pgval } { -1 } } + { \bool_set_true:N \l__zrefclever_next_maybe_range_bool } + { + \int_compare:nNnT + { \__zrefclever_extract:nnn {#1} { zc@pgval } { -1 } } + = + { \__zrefclever_extract:nnn {#2} { zc@pgval } { -1 } } + { + \bool_set_true:N \l__zrefclever_next_maybe_range_bool + \bool_set_true:N \l__zrefclever_next_is_same_bool + } + } + } + } + { + \exp_args:Nxx \tl_if_eq:nnT + { \__zrefclever_extract_unexp:nnn {#1} { zc@counter } { } } + { \__zrefclever_extract_unexp:nnn {#2} { zc@counter } { } } + { + \exp_args:Nxx \tl_if_eq:nnT + { \__zrefclever_extract_unexp:nnn {#1} { zc@enclval } { } } + { \__zrefclever_extract_unexp:nnn {#2} { zc@enclval } { } } + { + \int_compare:nNnTF + { \__zrefclever_extract:nnn {#1} { zc@cntval } { -2 } + 1 } + = + { \__zrefclever_extract:nnn {#2} { zc@cntval } { -1 } } + { \bool_set_true:N \l__zrefclever_next_maybe_range_bool } + { + \int_compare:nNnT + { \__zrefclever_extract:nnn {#1} { zc@cntval } { -1 } } + = + { \__zrefclever_extract:nnn {#2} { zc@cntval } { -1 } } + { + \bool_set_true:N + \l__zrefclever_next_maybe_range_bool + \exp_args:Nxx \tl_if_eq:nnT + { + \__zrefclever_extract_unexp:nvn {#1} + { l__zrefclever_ref_property_tl } { } + } + { + \__zrefclever_extract_unexp:nvn {#2} + { l__zrefclever_ref_property_tl } { } + } + { + \bool_set_true:N + \l__zrefclever_next_is_same_bool + } + } + } + } + } + } + } + } +\cs_new_protected:Npn \__zrefclever_get_ref_string:nN #1#2 + { + % First attempt: general options. + \prop_get:NnNF \l__zrefclever_ref_options_prop {#1} #2 + { + % If not found, try type specific options. + \bool_lazy_and:nnTF + { + \prop_if_exist_p:c + { + l__zrefclever_type_ + \l__zrefclever_label_type_a_tl _options_prop + } + } + { + \prop_if_in_p:cn + { + l__zrefclever_type_ + \l__zrefclever_label_type_a_tl _options_prop + } + {#1} + } + { + \prop_get:cnN + { + l__zrefclever_type_ + \l__zrefclever_label_type_a_tl _options_prop + } + {#1} #2 + } + { + % If not found, try type specific translations. + \__zrefclever_get_type_transl:xxnNF + { \l__zrefclever_ref_language_tl } + { \l__zrefclever_label_type_a_tl } + {#1} #2 + { + % If not found, try default translations. + \__zrefclever_get_default_transl:xnNF + { \l__zrefclever_ref_language_tl } + {#1} #2 + { + % If not found, try fallback. + \__zrefclever_get_fallback_transl:nNF {#1} #2 + { + \tl_clear:N #2 + \msg_warning:nnn { zref-clever } + { missing-string } {#1} + } + } + } + } + } + } +\cs_new_protected:Npn \__zrefclever_get_ref_font:nN #1#2 + { + % First attempt: general options. + \prop_get:NnNF \l__zrefclever_ref_options_prop {#1} #2 + { + % If not found, try type specific options. + \bool_if:nTF + { + \prop_if_exist_p:c + { + l__zrefclever_type_ + \l__zrefclever_label_type_a_tl _options_prop + } + } + { + \prop_get:cnNF + { + l__zrefclever_type_ + \l__zrefclever_label_type_a_tl _options_prop + } + {#1} #2 + { \tl_clear:N #2 } + } + { \tl_clear:N #2 } + } + } +\__zrefclever_compat_module:nn { appendix } + { + \AddToHook { cmd / appendix / before } + { + \__zrefclever_zcsetup:n + { + countertype = + { + chapter = appendix , + section = appendix , + subsection = appendix , + subsubsection = appendix , + paragraph = appendix , + subparagraph = appendix , + } + } + } + } +\__zrefclever_compat_module:nn { appendices } + { + \__zrefclever_if_package_loaded:nT { appendix } + { + \newcounter { zc@appendix } + \newcounter { zc@save@appendix } + \setcounter { zc@appendix } { 0 } + \setcounter { zc@save@appendix } { 0 } + \cs_if_exist:cTF { chapter } + { + \__zrefclever_zcsetup:n + { counterresetby = { chapter = zc@appendix } } + } + { + \cs_if_exist:cT { section } + { + \__zrefclever_zcsetup:n + { counterresetby = { section = zc@appendix } } + } + } + \AddToHook { env / appendices / begin } + { + \stepcounter { zc@save@appendix } + \setcounter { zc@appendix } { \value { zc@save@appendix } } + \__zrefclever_zcsetup:n + { + countertype = + { + chapter = appendix , + section = appendix , + subsection = appendix , + subsubsection = appendix , + paragraph = appendix , + subparagraph = appendix , + } + } + } + \AddToHook { env / appendices / end } + { \setcounter { zc@appendix } { 0 } } + \AddToHook { cmd / appendix / before } + { + \stepcounter { zc@save@appendix } + \setcounter { zc@appendix } { \value { zc@save@appendix } } + } + \AddToHook { env / subappendices / begin } + { + \__zrefclever_zcsetup:n + { + countertype = + { + section = appendix , + subsection = appendix , + subsubsection = appendix , + paragraph = appendix , + subparagraph = appendix , + } , + } + } + \msg_info:nnn { zref-clever } { compat-package } { appendix } + } + } +\__zrefclever_compat_module:nn { memoir } + { + \__zrefclever_if_class_loaded:nT { memoir } + { + \__zrefclever_zcsetup:n + { + countertype = + { + subfigure = figure , + subtable = table , + poemline = line , + } , + counterresetby = + { + subfigure = figure , + subtable = table , + } , + } + \cs_new_protected:Npn \__zrefclever_memoir_both_labels: + { + \cs_set_eq:NN \__zrefclever_memoir_orig_label:n \label + \cs_set:Npn \__zrefclever_memoir_label_and_zlabel:n ##1 + { + \__zrefclever_memoir_orig_label:n {##1} + \zlabel{##1} + } + \cs_set_eq:NN \label \__zrefclever_memoir_label_and_zlabel:n + } + \AddToHook { env / sidecaption / begin } + { \__zrefclever_memoir_both_labels: } + \AddToHook { env / sidecontcaption / begin } + { \__zrefclever_memoir_both_labels: } + \AddToHook{ cmd / bitwonumcaption / before } + { \group_begin: \__zrefclever_memoir_both_labels: } + \AddToHook{ cmd / bitwonumcaption / after } + { \group_end: } + \AddToHook{ cmd / bionenumcaption / before } + { \group_begin: \__zrefclever_memoir_both_labels: } + \AddToHook{ cmd / bionenumcaption / after } + { \group_end: } + \AddToHook{ cmd / bicaption / before } + { \group_begin: \__zrefclever_memoir_both_labels: } + \AddToHook{ cmd / bicaption / after } + { \group_end: } + \zref@newprop { subcaption } + { \cs_if_exist_use:c { @@thesub \@captype } } + \AddToHook{ cmd / @memsubcaption / before } + { \zref@localaddprop \ZREF@mainlist { subcaption } } + \tl_new:N \l__zrefclever_memoir_footnote_type_tl + \tl_set:Nn \l__zrefclever_memoir_footnote_type_tl { footnote } + \AddToHook { env / minipage / begin } + { \tl_set:Nn \l__zrefclever_memoir_footnote_type_tl { mpfootnote } } + \AddToHook { cmd / @makefntext / before } + { + \__zrefclever_zcsetup:x + { currentcounter = \l__zrefclever_memoir_footnote_type_tl } + } + \AddToHook { cmd / @makesidefntext / before } + { \__zrefclever_zcsetup:n { currentcounter = sidefootnote } } + \__zrefclever_zcsetup:n + { + countertype = + { + sidefootnote = footnote , + pagenote = endnote , + } , + } + \AddToHook { file / \jobname.ent / before } + { \__zrefclever_zcsetup:x { currentcounter = pagenote } } + \msg_info:nnn { zref-clever } { compat-class } { memoir } + } + } +\__zrefclever_compat_module:nn { KOMA } + { + \cs_if_exist:NT \KOMAClassName + { + \AddToHook { env / captionbeside / after } + { + \tl_if_exist:NT \@captype + { \tl_set_eq:NN \@currentcounter \@captype } + } + \tl_new:N \g__zrefclever_koma_captionofbeside_captype_tl + \AddToHook { env / captionofbeside / end } + { \tl_gset_eq:NN \g__zrefclever_koma_captype_tl \@captype } + \AddToHook { env / captionofbeside / after } + { + \tl_if_eq:NnF \@currenvir { document } + { + \tl_if_empty:NF \g__zrefclever_koma_captype_tl + { + \tl_set_eq:NN + \@currentcounter \g__zrefclever_koma_captype_tl + } + } + \tl_gclear:N \g__zrefclever_koma_captype_tl + } + \msg_info:nnx { zref-clever } { compat-class } { \KOMAClassName } + } + } +\__zrefclever_compat_module:nn { amsmath } + { + \__zrefclever_if_package_loaded:nT { amsmath } + { + \cs_set_nopar:Npn \__zrefclever_ltxlabel:n #1 + { + \__zrefclever_orig_ltxlabel:n {#1} + \zref@wrapper@babel \zref@label {#1} + } + \__zrefclever_if_package_loaded:nTF { hyperref } + { + \AddToHook { package / nameref / after } + { + \cs_new_eq:NN \__zrefclever_orig_ltxlabel:n \ltx@label + \cs_set_eq:NN \ltx@label \__zrefclever_ltxlabel:n + } + } + { + \cs_new_eq:NN \__zrefclever_orig_ltxlabel:n \ltx@label + \cs_set_eq:NN \ltx@label \__zrefclever_ltxlabel:n + } + \AddToHook { env / subequations / begin } + { + \__zrefclever_zcsetup:x + { + counterresetby = + { + parentequation = + \__zrefclever_counter_reset_by:n { equation } , + equation = parentequation , + } , + currentcounter = parentequation , + countertype = { parentequation = equation } , + } + } + \clist_map_inline:nn + { + equation , + equation* , + align , + align* , + alignat , + alignat* , + flalign , + flalign* , + xalignat , + xalignat* , + gather , + gather* , + multline , + multline* , + } + { + \AddToHook { env / #1 / begin } + { \__zrefclever_zcsetup:n { currentcounter = equation } } + } + \zcRefTypeSetup { equation } + { + reffont = \upshape , + refpre = {\textup{(}} , + refpos = {\textup{)}} , + } + \msg_info:nnn { zref-clever } { compat-package } { amsmath } + } + } +\bool_new:N \l__zrefclever_mathtools_showonlyrefs_bool +\__zrefclever_compat_module:nn { mathtools } + { + \__zrefclever_if_package_loaded:nT { mathtools } + { + \MH_if_boolean:nT { show_only_refs } + { + \bool_set_true:N \l__zrefclever_mathtools_showonlyrefs_bool + \cs_new_protected:Npn \__zrefclever_mathtools_showonlyrefs:n #1 + { + \@bsphack + \seq_map_inline:Nn #1 + { + \exp_args:Nx \tl_if_eq:nnTF + { \__zrefclever_extract_unexp:nnn {##1} { zc@type } { } } + { equation } + { + \protected@write \@auxout { } + { \string \MT@newlabel {##1} } + } + { + \exp_args:Nx \tl_if_eq:nnT + { \__zrefclever_extract_unexp:nnn {##1} { zc@type } { } } + { parentequation } + { + \protected@write \@auxout { } + { \string \MT@newlabel {##1} } + } + } + } + \@esphack + } + \msg_info:nnn { zref-clever } { compat-package } { mathtools } + } + } + } +\__zrefclever_compat_module:nn { breqn } + { + \__zrefclever_if_package_loaded:nT { breqn } + { + \AddToHook { env / dgroup / begin } + { + \__zrefclever_zcsetup:x + { + counterresetby = + { + parentequation = + \__zrefclever_counter_reset_by:n { equation } , + equation = parentequation , + } , + currentcounter = parentequation , + countertype = { parentequation = equation } , + } + } + \clist_map_inline:nn + { + dmath , + dseries , + darray , + } + { + \AddToHook { env / #1 / begin } + { \__zrefclever_zcsetup:n { currentcounter = equation } } + } + \msg_info:nnn { zref-clever } { compat-package } { breqn } + } + } +\__zrefclever_compat_module:nn { listings } + { + \__zrefclever_if_package_loaded:nT { listings } + { + \__zrefclever_zcsetup:n + { + countertype = + { + lstlisting = listing , + lstnumber = line , + } , + counterresetby = { lstnumber = lstlisting } , + } + \lst@AddToHook { PreInit } + { \tl_if_empty:NF \lst@label { \zlabel { \lst@label } } } + \lst@AddToHook { Init } + { \__zrefclever_zcsetup:n { currentcounter = lstnumber } } + \msg_info:nnn { zref-clever } { compat-package } { listings } + } + } +\__zrefclever_compat_module:nn { enumitem } + { + \__zrefclever_if_package_loaded:nT { enumitem } + { + \int_set:Nn \l_tmpa_int { 5 } + \bool_while_do:nn + { + \cs_if_exist_p:c + { c@ enum \int_to_roman:n { \l_tmpa_int } } + } + { + \__zrefclever_zcsetup:x + { + counterresetby = + { + enum \int_to_roman:n { \l_tmpa_int } = + enum \int_to_roman:n { \l_tmpa_int - 1 } + } , + countertype = + { enum \int_to_roman:n { \l_tmpa_int } = item } , + } + \int_incr:N \l_tmpa_int + } + \int_compare:nNnT { \l_tmpa_int } > { 5 } + { \msg_info:nnn { zref-clever } { compat-package } { enumitem } } + } + } +\__zrefclever_compat_module:nn { subcaption } + { + \__zrefclever_if_package_loaded:nT { subcaption } + { + \__zrefclever_zcsetup:n + { + countertype = + { + subfigure = figure , + subtable = table , + } , + counterresetby = + { + subfigure = figure , + subtable = table , + } , + } + \zref@newprop { subref } + { \cs_if_exist_use:c { thesub \@captype } } + \tl_put_right:Nn \caption@subtypehook + { \zref@localaddprop \ZREF@mainlist { subref } } + } + } +\__zrefclever_compat_module:nn { subfig } + { + \__zrefclever_if_package_loaded:nT { subfig } + { + \__zrefclever_zcsetup:n + { + countertype = + { + subfigure = figure , + subtable = table , + } , + counterresetby = + { + subfigure = figure , + subtable = table , + } , + } + } + } +\zcDeclareLanguage { english } +\zcDeclareLanguageAlias { american } { english } +\zcDeclareLanguageAlias { australian } { english } +\zcDeclareLanguageAlias { british } { english } +\zcDeclareLanguageAlias { canadian } { english } +\zcDeclareLanguageAlias { newzealand } { english } +\zcDeclareLanguageAlias { UKenglish } { english } +\zcDeclareLanguageAlias { USenglish } { english } +\zcDeclareLanguage + [ declension = { N , A , D , G } , gender = { f , m , n } , allcaps ] + { german } +\zcDeclareLanguageAlias { austrian } { german } +\zcDeclareLanguageAlias { germanb } { german } +\zcDeclareLanguageAlias { ngerman } { german } +\zcDeclareLanguageAlias { naustrian } { german } +\zcDeclareLanguageAlias { nswissgerman } { german } +\zcDeclareLanguageAlias { swissgerman } { german } +\zcDeclareLanguage [ gender = { f , m } ] { french } +\zcDeclareLanguageAlias { acadian } { french } +\zcDeclareLanguageAlias { canadien } { french } +\zcDeclareLanguageAlias { francais } { french } +\zcDeclareLanguageAlias { frenchb } { french } +\zcDeclareLanguage [ gender = { f , m } ] { portuguese } +\zcDeclareLanguageAlias { brazilian } { portuguese } +\zcDeclareLanguageAlias { brazil } { portuguese } +\zcDeclareLanguageAlias { portuges } { portuguese } +\zcDeclareLanguage [ gender = { f , m } ] { spanish } +%% +%% +%% End of file `zref-clever.sty'. diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index 4543aca6270..b5fe5c8f6b6 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -866,7 +866,7 @@ my @TLP_working = qw( yinit-otf york-thesis youngtab yplan yquant ytableau zapfchan zapfding zbmath-review-template zebra-goodies zed-csp zhlineskip zhlipsum zhnumber zhmetrics zhmetrics-uptex zhspacing - ziffer zitie zlmtt zootaxa-bst zref zref-check + ziffer zitie zlmtt zootaxa-bst zref zref-check zref-clever zwgetfdate zwpagelayout zx-calculus zxjafbfont zxjafont zxjatype zztex ); diff --git a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc index d3af70d4e19..dc923fcf8c0 100644 --- a/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-latexextra.tlpsrc @@ -1405,5 +1405,6 @@ depend zed-csp depend ziffer depend zref depend zref-check +depend zref-clever depend zwgetfdate depend zwpagelayout diff --git a/Master/tlpkg/tlpsrc/zref-clever.tlpsrc b/Master/tlpkg/tlpsrc/zref-clever.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d -- cgit v1.2.3