Compare commits

..

36 Commits

Author SHA1 Message Date
52e0e12f8f Distribute only the LaTeX PDF test file and keep it updated 2025-08-07 21:37:19 +02:00
b53f872423 Improved vertical spacing in the summary 2025-08-07 21:25:12 +02:00
025d19c11d typo in the manual 2025-08-07 20:46:36 +02:00
d9d9dde044 Corrections in the release script 2025-08-07 20:41:53 +02:00
690c83e48e Added the microfixes for the summary in the manual 2025-08-07 17:49:01 +02:00
7c10e26652 Cosmetic improvements in the manual 2025-08-07 17:41:04 +02:00
216eb55217 Updated version and date 2025-08-07 17:36:54 +02:00
cf72695316 Added the package version in the manual, dissociated from the date 2025-08-07 17:29:23 +02:00
e5b0db7cf4 Cosmetic improvements in the manual 2025-08-07 17:02:39 +02:00
e9ed29f53b Added a summary of the macros and config keys/macros 2025-08-07 16:37:17 +02:00
58deb3f384 TODO update date and version 2025-08-06 08:42:34 +02:00
6e5c153939 Minor improvements in the manual 2025-08-06 08:39:15 +02:00
eabdf91580 Implementation and documentation of \crfnmsetup 2025-08-06 08:38:39 +02:00
d09410db10 Better presentation of the supported reference types 2025-08-06 08:36:01 +02:00
ca9923e4a9 Suppression d'un TODO obsolète 2025-08-06 08:24:27 +02:00
2abff534a8 Make the test file compatible with \usepackage in crossrefenum.tex 2025-08-06 01:18:09 +02:00
e4a7a4a7dd Formatting improvements in the test file 2025-08-05 18:17:31 +02:00
4898173394 Small error in the manual 2025-08-05 16:10:11 +02:00
e6f59ea551 Reordering of code 2025-08-05 15:25:29 +02:00
e7f185555a Mise à jour de la documentation 2025-08-05 14:28:18 +02:00
f72a057ce4 Bug fix in the test file for ConTeXt 2025-08-05 14:13:17 +02:00
942371aef3 The last arg of \crossrefenum can now be a comma-delimited list 2025-08-05 12:48:06 +02:00
cbb190a907 Updated the test file (incl. adaptation of formatting macros) 2025-08-05 12:46:54 +02:00
d37e4efeb4 An empty list of references now gives an empty enumeration without prefix. 2025-08-05 12:16:38 +02:00
ac73606c99 Don't indent paragraphs in the changelog 2024-04-14 20:58:03 +02:00
e811c3a78a Switched tests to lualatex 2024-04-14 20:56:51 +02:00
cd1601abe0 Revert "Use t-crossrefenum.tex in the tests" (explained in t-crossrefenum.tex)
This reverts commit c0460c15a8.
2024-04-13 12:35:27 +02:00
77de7e82ce Updated metatada in t-crossrefenum.tex 2024-04-13 12:35:24 +02:00
9ee5e7efa3 Bump version number 2024-04-13 12:27:53 +02:00
81d9cd4bde Fixes in typesetting the manual 2024-04-13 12:14:35 +02:00
c3dd41d8e6 Added convenience macros to add types 2024-04-13 11:55:19 +02:00
c0460c15a8 Use t-crossrefenum.tex in the tests 2024-04-13 10:49:25 +02:00
f98bd8927e Fixes in the manual 2024-04-13 10:48:01 +02:00
ff8d813637 Updated the template for Pandoc and slightly improved the manual 2023-02-20 21:35:57 +01:00
fec1feff3b typo + version 2023-02-20 21:12:39 +01:00
59233a91f7 Updated version and copyright date 2023-02-20 21:06:42 +01:00
16 changed files with 8598 additions and 1272 deletions

View File

@ -1,7 +1,33 @@
## Changes
```{=context}
\parindent=0pt
```
### 2022/11/11: Version 1.0
### 2023/02/20: Version 1.0.1
`\crossrefenum` is now protected against early expansion.
### 2023/02/20: Version 1.0.2
Fixed some minor issues in version numbers and in the manual.
### 2024/04/13: Version 1.1
Various fixes in the documentation and new convenience macro `\crfnm@declareType`.
The test suite now uses _lualatex_.
### 2025/08/07: Version 1.2
The last argument of `\crossrefenum` can now be a comma-delimited list
instead of a list of groups. Lists of groups are still supported and will remain so.
The new macro `\crfnmsetup` now provides a key-value configuration interface,
thanks to Jonathan `\penalty-10000`{=context} P. Spratte's
[`expkv`](https://ctan.org/pkg/expkv-bundle) package.
The dependency to `expkv` can be removed by deactivating the key-value interface.
Various improvements in the manual.

View File

@ -1,8 +1,8 @@
# crossrefenum 2023/02/20 v1.0.1
# crossrefenum 2025/08/07 v1.2
Smart typesetting of enumerated cross-references for various TeX formats.
Copyright (C) 2022
Copyright (C) 2022-2025
by Bastien Dumont <bastien.dumont@posteo.net>
CTAN: `macros/generic/crossrefenum`
@ -13,9 +13,12 @@ _crossrefenum_ lets TeX manage the formatting
of bunches of cross-references for you. It features:
* Automatic collapsing of references;
* Support for references by various criteria,
including page and note number, line number in ConTeXt
and edpage and edline when used in conjunction with _reledmac_;
* Support for references by various criteria:
* page and note number;
* in ConTeXt: line number;
* in LaTeX, when used in conjunction with _reledmac_: edpage and edline.
* Handling of references combining two criteria
(e.g. by page and note number);
* Extension mechanisms to add support to other types of references
@ -28,6 +31,9 @@ the labels they refer to appear in their document.
It is written in Plain TeX as much as possible
in order to make it compatible with a wide array of formats.
For the moment, it works out of the box with ConTeXt and LaTeX.
It only depends on [`expkv`](https://ctan.org/pkg/expkv-bundle)
(but this dependency can be removed by deactivating
the key-value configuration interface in favor of the native configuration macros).
## List of files
@ -48,9 +54,8 @@ For the moment, it works out of the box with ConTeXt and LaTeX.
* `data-lines.tex`: _Text input to test line numbering._
* `data-reledmac.tex`: _Text input for *reledmac*._
* `format-specific-defs.tex`: _Definition of the macros used in the test and data files that depend on format-specific macros._
* `main-test_context.pdf`: _Test file generated with ConTeXt._
* `main-test_latex.pdf`: _Test file generated with LaTeX._
* `main-test.tex`: _Main test file._
* `main-test.pdf`: _Test file generated with LaTeX._
* `main-test.tex`: _Main test file (can also be compiled with ConTeXt)._
* `Makefile`: _Provides targets to generate the test file (`test` for LaTeX, `test-context`) and to `check` its correctness._
* `validated_output`: _Used by `make check`._
* `tex/`
@ -66,7 +71,7 @@ and put in it `crossrefenum.tex` and, if required,
## License
Copyright 2022 by Bastien Dumont (bastien.dumont@posteo.net)
Copyright 2022-2025 by Bastien Dumont (bastien.dumont@posteo.net)
crossrefenum.tex is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

View File

@ -1,6 +1,10 @@
crossrefenum.pdf: crossrefenum.md ../CHANGELOG.md \
TEMPLATE_crossrefenum.context fixes.lua
pandoc -o crossrefenum.pdf --pdf-engine=context \
crossrefenum.pdf: crossrefenum-doc.tex
context $< && mv crossrefenum-doc.pdf $@
crossrefenum-doc.tex: crossrefenum.md ../CHANGELOG.md \
TEMPLATE_crossrefenum.context fixes.lua
pandoc -s -o $@ -t context-smart \
--template=TEMPLATE_crossrefenum.context \
-L fixes.lua \
crossrefenum.md ../CHANGELOG.md
sh ./microfixes-doc.sh $@

View File

@ -22,8 +22,8 @@ $endif$
\setupbodyfontenvironment[default][em=italic]
\definefontfamily[mainface][rm][cochineal]
\definefontfamily[mainface][ss][linuxbiolinumo]
\definefontfamily[mainface][tt][nimbusmonops][features=none]
\definefontfamily[mainface][ss][libertinussans]
\definefontfamily[mainface][tt][dejavusansmono][features=none, rscale=0.78]
\setupbodyfont[mainface,12pt]
\setuptype[lines=no]
@ -39,7 +39,7 @@ $endif$
\setuppagenumbering[location=] % Pour que le numéro de page n'apparaisse pas en haut au milieu
\setupheader[text][leftstyle=\em]
\setupheadertexts[section][pagenumber]
\setupfootertexts$if(toc)$[{\inframed{\goto{Table of contents}[page(3)]}}]$endif$[{\inframed{\goto{Jump to previous page}[PreviousJump]}}]
\setupfootertexts$if(toc)$[{\inframed{\goto{Table of contents}[page(3)]}}]$endif$[{\inframed{\goto{Summary}[page(7)]}}]
\setupbackend[
format={pdf/a-1a:2005},
@ -69,7 +69,7 @@ intent=ISO coated v2 300\letterpercent\space (ECI)]
\setupitemize[1][symbol=emdash, width=2.2em, indenting=-0.7em] % cochineal has no bullet
\setupitemize[2][symbol=endash, width=1.3em, indenting=-0.3em]
\setupdelimitedtext[blockquote][indenting=no]
\setupdelimitedtext[blockquote][indenting=big,style=\tta,before=\blank[big],after=\blank[big]]
\definebreakpoints[lbreakwithouthyphen]
\definebreakpoint[lbreakwithouthyphen][=][type=1]
@ -88,9 +88,14 @@ intent=ISO coated v2 300\letterpercent\space (ECI)]
\setuplist[subsection][margin=3em, width=3em]
\setuplist[subsubsection][margin=6em, width=4em]
$if(highlighting-commands)$
$highlighting-commands$
$endif$
\starttext
\starttitlepagemakeup
\vfil
$if(title)$
{\tfd\setupinterlinespace $title$}
$if(subtitle)$
@ -99,12 +104,23 @@ $if(subtitle)$
$endif$
$if(author)$
\blank[force,1cm]
{\tfa\setupinterlinespace $for(author)$$author$$sep$\crlf $endfor$}
{\tfa\setupinterlinespace $author$}
$endif$
$if(date)$
$if(version)$
\blank[force,1cm]
{\tfa\setupinterlinespace $date$}
{\tfb\setupinterlinespace v. $version$}
$endif$
\vfil
\vskip1cm
$if(date)$
\blank[force,.7cm]
{\tfx\setupinterlinespace Last update of this manual: $date$}
$endif$
$if(email)$
\blank[force,small]
{\tfx Contact: }{\ttx $email$}
$endif$
\vskip-2cm
\stoptitlepagemakeup
\pagebreak
$endif$
@ -112,7 +128,7 @@ $endif$
$if(license)$
\startlicensepagemakeup
\inframed[frame=off, width=0.66\textwidth, align=normal]{%
Copyright (C) 2022 Bastien Dumont.
Copyright (C) 2022-2025 Bastien Dumont.
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3
or any later version published by the Free Software Foundation;
@ -132,4 +148,4 @@ $endif$
$body$
\stoptext
\stoptext

View File

@ -2,7 +2,9 @@
title: "crossrefenum"
subtitle: "Smart typesetting of enumerated cross-references for various TeX formats"
author: Bastien Dumont
date: 2022/11/11
email: bastien [dot] dumont [at] posteo [dot] net
date: "2025/08/07"
version: 1.2
lang: en-US
toc: true
license: true
@ -12,9 +14,12 @@ _crossrefenum_ lets TeX manage the formatting
of bunches of cross-references for you. It features:
* Automatic collapsing of references;
* Support for references by various criteria,
including page and note number, line number in ConTeXt
and edpage and edline when used in conjunction with _reledmac_;
* Support for references by various criteria:
* page and note number;
* in ConTeXt: line number;
* in LaTeX, when used in conjunction with _reledmac_: edpage and edline.
* Handling of references combining two criteria
(e.g. by page and note number);
* Extension mechanisms to add support to other types of references
@ -27,6 +32,9 @@ the labels they refer to appear in their document.
It is written in Plain TeX as much as possible
in order to make it compatible with a wide array of formats.
For the moment, it works out of the box with ConTeXt and LaTeX.
Its only (optional) dependency is [`expkv`](https://ctan.org/pkg/expkv-bundle),
but it may require other packages to work properly in some formats
(e.g. [`zref`](https://ctan.org/pkg/zref) in LaTeX).
The file `main-test.pdf` provides a showcase of the abilities of _crossrefenum_.
@ -40,43 +48,205 @@ you can do:
* `\input{crossrefenum}` (generic);
* `\usepackage{crossrefenum}` (LaTeX;
must be called after _nameref_ if you use _hyperref_);
must be called after _nameref_ if you use _hyperref_`\kern1.5pt`{=context});
* `\usemodule[crossrefenum]` (ConTeXt).
## Basic invocation
## Summary {#summary}
* [`\crossrefenum`](#macro-crossrefenum): the main macro
* [`\crfnmsetup`](#crfnmsetup-macro): configuration macro (default of per type)
```{=context}
\vskip\medskipamount
```
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|**Configuration |**Configuration macro (with `\def`)** |**Meaning** |**Example** |**Page** |
|key (with | | | | |
|`\crfnmsetup`)** | | | | |
+=================+===============================================+=====================+==============+==============================+
|`<type>` _is a single type_ |`page` |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`sg` |`\crfnm<type>` |Singular prefix |`{p. }` |`\at[prefixes]`{=context} |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`pl` |`\crfnm<type>s` |Plural prefix |`{pp. }` |`\at[prefixes]`{=context} |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`delimiter` |`\crfnm<type>EnumDelim` |Delimiter between |`{, }` |`\at[delimiters]`{=context} |
| | |references | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`before last |`\crfnm<type>BeforeLastInEnum` |Delimiter before the |`{ and }` |`\at[delimiters]`{=context} |
|reference` | |last reference | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`range separator`|`\crfnm<type>RangeSep` |Separator between the|`{\tt |`\at[range-sep]`{=context} |
| | |two values in a range|`{=context} | |
| | | |`}`{=context} | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`collapsable?` |`\crfnm<type>Collapsable` |Should consecutive |`yes` or `no` |`\at[collapsable]`{=context} |
| | |numbers (e.g. 2, 3, | | |
| | |4) be merged into a | | |
| | |range? | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`<type>` _is a double type_ |`pagenote` |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`subtypes |`\crfnm<type>SubtypesSep` |Separator between the|`{, }` |`\at[subtypes-sep]`{=context} |
|separator` | |two types of | | |
| | |references in a | | |
| | |double reference | | |
| | |(e.g. between the | | |
| | |page and note numbers| | |
| | |in a reference to a | | |
| | |note including the | | |
| | |page number) | | |
| | | | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`print prefix of |`\crfnm<type>PrintFirstPrefix` |Should the numbers of|`always` or |`\at[fst-pref-dbl]`{=context} |
|first subtype` | |the first subtype be |`once` | |
| | |prefixed always or | | |
| | |only for the first | | |
| | |reference in an | | |
| | |enumeration? | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`group subtypes?`|`\crfnm<type>GroupSubtypes` |Sould all the values |`yes` or `no` |`\at[group-subt]`{=context} |
| | |for each subtype be | | |
| | |printed separately? | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`order` |`\crfnm<type>Order` |Whether the subtypes |`normal` or |`\at[order]`{=context} |
| | |are printed in the |`inverted` | |
| | |same order as in the | | |
| | |name of the double | | |
| | |type | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`<type>` _is a single type; the following options apply when it is used as the second |`page` |
|subtype of a double type_ | |
| | |
| | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`formatting when |`\crfnm<type>FormatInSecond` |`{}` or a macro that |`\textbf` |`\at[fmt-sec-subt]`{=context} |
|second subtype` | |takes the prefixes | | |
| | |and numbers as its | | |
| | |argument | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`print prefix |`\crfnm<type>PrintPrefixInSecond` |Should the prefix be |`yes` or `no` |`\at[rep-pref-dbl]`{=context} |
|when second | |printed? | | |
|subtype?` | | | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`delimiter when |`\crfnm<type>EnumDelimInSecond` |Delimiter between |`{, }` |`\at[delim-sec-dbl]`{=context}|
|second subtype` | |references | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`before last |`\crfnm<type>BeforeLastInSecond` |Delimiter before the |`{ and }` |`\at[delim-sec-dbl]`{=context}|
|reference when | |last reference | | |
|second subtype` | | | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`continuous |`\crfnm<type>NumberingContinuousAcrossDocument`|Is the numbering for |`yes` or `no` |`\at[numb-contin]`{=context} |
|numbering?` | |this type continuous | | |
| | |(i.e. not reset at | | |
| | |every | | |
| | |page/chapter/etc.)? | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
## Basic invocation {#macro-crossrefenum}
The macro `\crossrefenum` has the following syntax:
> \\crossrefenum\[_type_\]\[_print prefix?_\]{_enumeration_}
> \\crossrefenum[\<type\>][\<print prefix?\>]{\<enumeration\>}
* _type_ is the type of reference. Built-in possible values are:
* _type_ is the type of the references. Built-in possible values are:
* For LaTeX and ConTeXt: `page`, `note`, `pagenote`;
* For ConTeXt only: `line`, `pageline`;
* For LaTeX with _reledmac_: `edpage`, `edline`, `edpageline`.
* _print prefix?_ indicates whether the prefix (like “p. ”) should be printed or not: true if set to `withprefix` or `yes`;
* _enumeration_ is a group containing one or more _single_ labels (e.g. `{mylabel}`) or _ranges_ (e.g. `{lbl-begin to lbl-end}`) included in groups. Ranges cannot be used with `note` and `pagenote` types.
* _enumeration_ is a group containing one or more _single_ labels (e.g. `mylabel`) or _ranges_ (e.g. `lbl-begin to lbl-end`).
Ranges cannot be used with `note` and `pagenote` types.
Two syntaxes are supported: lists of groups and comma-delimited lists (see below).
_type_ and _print prefix?_ are optional. _type_ defaults to `page` and _print prefix_ to `withprefix`.
Here are some valid invocations:
Here are some valid invocations with the comma-delimited syntax:
* `\crossrefenum[note][withprefix]{lblone, lbltwo, lblthree}`
* `\crossrefenum[edline][noprefix]{lblone, lbltwo, lblthree}`
* `\crossrefenum[page]{lblone to lbltwo, lblthree}`
* `\crossrefenum[noprefix]{lblone, lbltwo, lblthree}` (_type_ defaults to `page`)
* `\crossrefenum[note]{lblone, lbltwo, lblthree}` (_print prefix?_ defaults to `withprefix`)
* `\crossrefenum{lblone, lbltwo, lblthree}` (_type_ defaults to `page` and _print prefix?_ defaults to `withprefix`)
* `\crossrefenum{only-one}`
The same invocations with the group-based syntax:
* `\crossrefenum[note][withprefix]{{lblone}{lbltwo}{lblthree}}`
* `\crossrefenum[edline][noprefix]{{lblone}{lbltwo}{lblthree}}`
* `\crossrefenum[noprefix]{{lblone}{lbltwo}{lblthree}}` (_type_ defaults to `page`)
* `\crossrefenum[note]{{lblone}{lbltwo}{lblthree}}` (_print prefix?_ defaults to `withprefix`)
* `\crossrefenum{{lblone}{lbltwo}{lblthree}}` (_type_ defaults to `page` and _print prefix?_ defaults to `withprefix`)
* `\crossrefenum{{only-one}}` (even if the enumeration is limited to one item, it must be inside its own group)
* `\crossrefenum[page]{{lblone to lbltwo}{lblthree}}`
* `\crossrefenum[noprefix]{{lblone}{lbltwo}{lblthree}}`
* `\crossrefenum[note]{{lblone}{lbltwo}{lblthree}}`
* `\crossrefenum{{lblone}{lbltwo}{lblthree}}`
* `\crossrefenum{{only-one}}` (even if the enumeration is limited to one item, it can be inside its own group)
## Customization
## Customization {#crfnmsetup-macro}
Customizing is done by redefining configuration macros.
We describe the general mechanism first.
Macros for double types are introduced at the end of this section.
There are two configuration interfaces:
one based on key-value lists, the other on (re)defining macros.
These two interfaces can be used concurrently.
If you are not interested in using the key-value interface
or prefer not to depend on the `expkv` package,
you can deactivate it by defining `\crfnmNoKV` to anything other than `\relax`
before loading `crossrefenum`.
After having explained the general principles,
we will present the options related to single types
before we turn to the options specific to double types and their subtypes.
For each configuration option, I will show
first how to use the key-value interface using `\crfnmsetup`,
and second how to do the same thing with the low-level macros.
### General principles {#specialize-config-macros}
In this manual, “default” means “not type-specific”.
In this respect, “default” settings may be set be the user.
The key-value interface has the following syntax:
> \\crfnmsetup[<“default” or type>]{ \<key1\> = \<value1\>, <…> }
_type_ is a single or a double type (e.g. `page` or `pagenote`).
The spaces around the equal signs and the commas are optional and ignored;
if a value contains leading or trailing spaces, it must be put inside a group
(e.g. `delimiter = {, }`).
Under the hood, `\crfnmsetup` (re)defines the low-level configuration macros,
which you can also manipulate directly.
When successive calls to `\crfnmsetup` contradict one another, the last one prevails,
except that type-specific settings always have precedence over the default ones.
In the following subsections, I will generally present the low-level macros
corresponding to the default settings, which have `Default` in their name.
If you want to redefine a macro for a specific type,
simply replace `Default` with the (capitalized) name of the type
(e.g. `\crfnmPageEnumDelim` instead of `\crfnmDefaultEnumDelim`).
Setting a value in the key-value interface or a macro to `\relax`
will cause `\crossrefenum` to fall back to the default value.
To set a configuration option to an absence of operation,
use an empty group (e.g. `\def\crfnmPageEnumDelim{}`
if you really don't want any delimiter between page numbers
while the default delimiter is a comma followed by a space).
Unless specified otherwise, the examples in the following subsections
correspond to the built-in configuration.
### Prefixes, delimiters and separators
Every simple type has two macros corresponding to the singular and plural prefixes
printed before the value of the reference. By default, they are set to:
You can define the [singular and plural prefixes]{#prefixes}
printed before the value of the reference like this:
```{.tex}
\crfnmsetup[page]{sg={p.~}, pl={pp.~}}
\crfnmsetup[note]{sg={n.~}, pl={nn.~}}
\crfnmsetup[edpage]{sg={p.~}, pl={pp.~}}
\crfnmsetup[edline]{sg={l.~}, pl={ll.~}}
```
`\noindentation`{=context} which almost amounts to the built-in configuration:
```{.tex}
\def\crfnmPage{p.~}
@ -89,91 +259,166 @@ printed before the value of the reference. By default, they are set to:
\def\crfnmEdlines{ll.~}
```
Between successive items in an enumeration, `\crossrefenum` calls `\crfnmDefaultEnumDelim` or `\crfnmDefaultBeforeLastInEnum`. By default, they are set to:
`\noindentation`{=context} (it would have been more accurate to write
`\crfnmsetup[edpage]{sg=\crfnmPage, pl=\crfnmPages}`).
The [delimiters]{#delimiters} printed respectively between the successive references in an enumeration
and before the last one are set so:
```{.tex}
\crfnmsetup[default]{
delimiter = {, },
before last reference = { and }
}
```
`\noindentation`{=context} which amounts to:
```{.tex}
\def\crfnmDefaultEnumDelim{, }
\def\crfnmDefaultBeforeLastInEnum{ and }
```
The beginning and the end of a range are separated by `\crfnmDefaultRangeSep`. By default:
The [separator in a range]{#range-sep} is set like this:
```{.tex}
\crfnmsetup[default]{range separator = }
```
`\noindentation`{=context} which amounts to:
```{.tex}
\def\crfnmDefaultRangeSep{}
```
### Collapsable and non-collapsable types {#collapsable-types}
### Collapsable and non-collapsable types {#collapsable}
The macro `\crfnmDefaultCollapsable` defines if ranges are allowed.
The default configuration is:
The configuration option `collapsable?` and
the macro `\crfnmDefaultCollapsable` define if ranges are allowed.
The built-in configuration corresponds to:
```{.tex}
\crfnmsetup[default]{collapsable?=yes}
\crfnmsetup[note]{collapsable?=no}
```
`\noindentation`{=context} which amounts to:
```{.tex}
\def\crfnmDefaultCollapsable{yes}
\def\crfnmNoteCollapsable{no}
```
Thus, a reference to consecutive notes is formatted like _nn. 3, 4 and 5_, not like _nn. 35_.
Thus, unless you change that, a reference to consecutive notes
is formatted like “nn. 3, 4 and 5”, not like “nn. 35”.
Ranges are not accepted in the argument of `\crossrefenum` for non-collapsable types.
This extends to double types that include a non-collapsable type
(such as `pagenote` in the default configuration).
(such as `pagenote` in the built-in configuration).
### Double types
Two subtypes in a double type (e.g. page and note number for `pagenote`)
are separated by `\crfnmDefaultSubtypesSep`. Default:
You can set like this [the separator between the two values in a double reference]{#subtypes-sep}
(e.g. the page and the note numbers in a `pagenote` reference):
```{.tex}
\crfnmsetup[default]{subtypes separator={, }}
```
`\noindentation`{=context} which amounts to:
```{.tex}
\def\crfnmDefaultSubtypesSep{, }
```
When more than one reference is cited in an enumeration,
you may not want the first prefix to be repeated every time
(e.g. you could prefer “pp. 5, n. 2; 7, n. 4” over “p. 5, n. 2; p. 7, n. 4”).
In that case, set `\crfnmDefaultPrintFirstPrefix` to `once`.
Default is:
[you may not want the first prefix to be repeated every time]{#fst-pref-dbl}
(e.g. you may prefer “pp. 5, n. 2; 7, n. 4” to “p. 5, n. 2; p. 7, n. 4”).
In this case, set `print prefix of first subtype`
or `\crfnmDefaultPrintFirstPrefix` to `once`.
Otherwise you will get:
```{.tex}
\crfnmsetup[default]{
print prefix of first subtype = always
}
```
`\noindentation`{=context} which amounts to:
```{.tex}
\def\crfnmDefaultPrintFirstPrefix{always}
```
If you want to format the second part of the reference in a special way (e.g. in superscript),
use `\crfnmDefaultFormatInSecond`,
which takes one argument which corresponds to the reference number and all its affixes.
Default is:
If you want to [format the second subtype]{#fmt-sec-subt} in a special way (e.g. in superscript),
set the key `formatting when second subtype` either to `{}` (no formatting)
or to a macro which will take the reference number and all its affixes as its only argument (e.g. `\textsuperscript`).
Alternatively, you can define `\crfnmDefaultFormatInSecond` with one argument.
What `\crossrefenum` comes with is:
```{.tex}
\crfnmsetup[default]{formatting when second subtype = {}}
```
`\noindentation`{=context} which amounts to:
```{.tex}
\def\crfnmDefaultFormatInSecond#1{#1}
```
If you don't want any prefix to be printed in the second term of a double reference,
set `\crfnmDefaultPrintPrefixInSecond` to `no` (default is yes).
For instance:
[If you don't want any prefix to be printed in the second term of a double reference]{#rep-pref-dbl},
set `print prefix when second subtype?`
or `\crfnmDefaultPrintPrefixInSecond` to `no` (built-in: yes).
Here is how you can print the line number in superscript
when it comes after the corresponding page number:
```{.tex}
\crfnmsetup[edline]{
formatting when second subtype = \textsuperscript,
print prefix when second subtype? = no
}
```
`\noindentation`{=context} which amounts to:
```{.tex}
\def\crfnmEdlineFormatInSecond#1{\textsuperscript{#1}}
\def\crfnmEdlinePrintPrefixInSecond{no}
\crossrefenum[edpageline]{{mylabel}}
```
`\noindentation`{=context} may return “p. 5^10^”, while `\crossrefenum[edline]{{mylabel}}` would return “l. 10”.
For the second part of such an enumeration (e.g. “l. 10” in “p. 5, l. 10”),
you can specify a specific delimiter
and a specific string to be printed before the last reference:
for instance, you may want to use the word “and”
before the last note number if the reference type is a simple one (`note`),
After that, `\crossrefenum[edpageline]{mylabel}` may return “p. 5^10^”,
whereas `\crossrefenum[edline]{mylabel}` would return “l. 10”.
You can specify a [specific delimiter for the second part of double references]{#delim-sec-dbl}
and a specific string to be printed before the last reference of the second subtype in a double reference
(e.g. the last reference to a line in “p. 5, l. 10, 13, 16”, which is “16”).
For instance, you may want to use the word “and”
before the last note number if the reference type is a simple one (`note`)
and a comma if it is comes in second in a double reference (e.g. in `pagenote`).
To achieve this, you should redefine `\crfnmDefaultEnumDelimInSecond`
and `\crfnmDefaultBeforeLastInEnumInSecond`.
By default, these macros fall back respectively
on `\crfnmDefaultEnumDelim` and `\crfnmDefaultBeforeLastInEnum`.
To achieve this, you can set `delimiter when second subtype` (= `\crfnmDefaultEnumDelimInSecond`)
and `before last reference when second subtype`
(= `\crfnmDefaultBeforeLastInSecond`).
In the built-in configuration, there is no difference between a simple type used alone
and the same simple type taken as the second subtype of a double type,
but we could imagine the following:
When citing a range, the two parts of the reference can
either be split (e.g. “p. 5, l. 3 p. 7, l. 44”)
```{.tex}
\crfnmsetup[note]{
delimiter = {; },
before last reference = { and },
delimiter when second subtype = {, },
before last reference when second subtype = {, }
}
\crossrefenum[note]{lbl1, lbl2, lbl3}
= \crossrefenum[pagenote]{lbl1, lbl2, lbl3}
```
`\noindentation`{=context} which may yield: “n. 1; 2 and 5 = p. 8, n. 1, 2, 5”.
[When citing a range, the two parts of the reference]{#group-subt} can
be either split (e.g. “p. 5, l. 3 p. 7, l. 44”)
or grouped (“p. 57, l. 344”).
This is controlled via `\crfnmDefaultGroupSubtypes`, which can be set to `yes` or `no`.
This works only with [collapsable types](#collapsable-types).
Default is:
This is controlled via `group subtypes?` (= `\crfnmDefaultGroupSubtypes`),
which can be set to `yes` or `no`.
This works only with [collapsable types](#collapsable):
```{.tex}
\crfnmsetup[default]{group subtypes? = no}
```
`\noindentation`{=context} which amounts to:
```{.tex}
\def\crfnmDefaultGroupSubtypes{no}
@ -181,40 +426,32 @@ Default is:
To know if a reference to “p. 6, l. 34” should be merged with “p. 7, l. 35”,
_crossrefenum_ needs to know if the lineation is
continuous (in this case, these lines are consecutive)
[continuous]{#numb-contin} (in this case, these lines are consecutive)
or per page (they are not, so they should not be merged).
You can set accordingly
`\crfnmDefaultNumberingContinuousAcrossDocument`[^line-numbering] to `yes` (default) or `no`.
You can set accordingly `continuous numbering?`
(= `\crfnmDefaultNumberingContinuousAcrossDocument`)[^line-numbering]
to `yes` (built-in) or `no`.
Note that _crossrefenum_ cannot merge a reference
to the last line of a page and the first line of the following page
if the lineation is not continuous.
[^line-numbering]: In this case, you could set more specifically
`\crfnmLineNumberingContinuousAcrossDocument`
or `\crfnmEdlineNumberingContinuousAcrossDocument`:
see [the following subsection](#specialize-config-macros).
By default, the number of the first subtype in the name of the double type
(e.g. “page” in “pagenote”) is always displayed first.
If you want to change this, set `\crfnmDefaultOrder` to `inverted` (defaults to `normal`).
### Specific values for given types {#specialize-config-macros}
If you want to override some of these macros for a specific type,
simply replace `Default` in its name with the (capitalized) name of the type
(e.g. `\def\crfnmPageEnumDelim{; }`).
Setting one of these macros to `\relax` will cause `\crossrefenum`
to use the corresponding default macro instead.
If you want a specific macro to be set to nothing,
use an empty group (e.g. `\def\crfnmPageEnumDelim{}`).
or `\crfnmEdlineNumberingContinuousAcrossDocument`
or use `\crfnmsetup` with `[line]` and `[edline]`.
In the built-in configuration, the [order of the subtypes]{#order} in the name of a subtype
(e.g. “page” and “note” in “pagenote”) determines by default
the order in which they are printed (e.g. “p. 6, n. 2” instead of “n. 2, p. 6”).
If you want to change this, set `order` (= `\crfnmDefaultOrder`) to `inverted` (built-in: `normal`).
## How to extend crossrefenum with other types and formats {#extending}
Adding support for new types consists in defining the related macros in your preamble.
Here is a commented example that would add support for references to lines in ConTeXt
if this feature were not already included in _crossrefenum_.
I suppose that the labels are inserted in the document using the standard ConTeXt macros,
i.e. `\someline` for line references and `\pagereference` for page references.
```{.tex}
% Register the types. Take care about capitalization!
@ -226,11 +463,11 @@ if this feature were not already included in _crossrefenum_.
\def\crfnm@pageline{Pageline}
%% Add them to the lists of known types.
\crfnm@newListFrom[\crfnm@simpleRefTypes][\crfnm@line] -> \crfnm@simpleRefTypes
\crfnm@newListFrom[\crfnm@doubleRefTypes][\crfnm@pageline] -> \crfnm@doubleRefTypes
\crfnm@newListFrom[\crfnm@supportedTypes][\crfnm@line] -> \crfnm@supportedTypes
\crfnm@newListFrom[\crfnm@supportedTypes][\crfnm@pageline] -> \crfnm@supportedTypes
\crfnm@declareType[simple][\crfnm@line]
\crfnm@declareType[double][\crfnm@pageline]
```
```{.tex}
%% For the double types, set the primary and the secondary type.
%% The primary type corresponds to the widest typographic unit
%% (“page” for “pagenote”, “section” for “sectionpage”...).
@ -242,6 +479,7 @@ if this feature were not already included in _crossrefenum_.
% Define the macro used by \crossrefenum internally
% to retrieve the raw reference number without typesetting it.
% This macro must be purely expandable.
% If you want to support multiple formats,
% see how the macro \crfnm@case is used in crossrefenum.tex.
% Note: the Lua function get_raw_ref_number is defined
@ -249,13 +487,16 @@ if this feature were not already included in _crossrefenum_.
\def\crfnm@getLineNumber#1{\directlua{get_raw_ref_number('lr:b:#1', 'linenumber')}}
% Define all specific configuration options in the regular way.
% Instead of the following, you can use \crfnmsetup.
```
```{.tex}
%% Required
\def\crfnmLine{l. }
\def\crfnmLines{ll.}
\def\crfnmLine{l.~}
\def\crfnmLines{ll.~}
%% If it differs from the defaults.
\def\crfnmCollapsable{yes}
\def\crfnmLineCollapsable{yes}
\def\crfnmLineBeforeLastInSecond{, }
\def\crfnmPagelineSubtypesSep{}
\def\crfnmPagelinePrintFirstPrefix{once}
@ -263,7 +504,7 @@ if this feature were not already included in _crossrefenum_.
\def\crfnmLinePrintPrefixInSecond{no}
```
Adding support to yet unsupported formats is far less trivial,
Adding support for additional formats is far less trivial,
not least because most of them do not provide a straightforward way
to get reference numbers via purely expandable macros,
which is required for _crossrefenum_ to perform its calculations.
@ -271,7 +512,7 @@ If you have wishes or hints about this, please contact me.
## Compatibility issues
With LaTeX, the _nameref_ package (required by _hyperref_)
With LaTeX, the _nameref_ package (required by _hyperref_`\kern1.5pt`{=context})
must be loaded explicitely before _crossrefenum_.
However, if the links in the output of `\crossrefenum` (not the numbers)
point to a wrong location, you may wish to patch the macro
@ -280,7 +521,9 @@ to disable _hyperref_ locally:
``` {.tex}
\makeatletter
\let\oldcrfnm@enum\crfnm@enum
\def\crfnm@enum[#1][#2]#3{\begin{NoHyper}\oldcrfnm@enum[#1][#2]{#3}\end{NoHyper}}
\def\crfnm@enum[#1][#2]#3{%
\begin{NoHyper}\oldcrfnm@enum[#1][#2]{#3}\end{NoHyper}%
}
\makeatother
```

View File

@ -5,10 +5,12 @@ local function set_break_points(code)
local broken_code = {}
for a, b in string.gmatch(raw_code, '([^a-zA-Z\\]?)([A-Z\\]?[a-z.]*)') do
if a ~= '' then
a = string.gsub(a, ' ', ' ') -- the leading/trailing spaces get gobbled
table.insert(broken_code, ZERO_WD_SP)
table.insert(broken_code, pandoc.Code(a))
table.insert(broken_code, pandoc.Code(a))
end
if b ~= '' then
b = string.gsub(b, ' ', ' ')
table.insert(broken_code, ZERO_WD_SP)
table.insert(broken_code, pandoc.Code(b))
end

10
doc/microfixes-doc.sh Normal file
View File

@ -0,0 +1,10 @@
sed -i 's/\\startplacetable\[location=none\]//' "$1"
sed -i 's/\\stopplacetable//' "$1"
sed -i 's/\\startxtable$/\\startxtable[toffset=.16\\baselineskip,boffset=.16\\baselineskip,frame=off,split=yes]/' "$1"
sed -i 's/width={0\.13/width={0.25/' "$1"
sed -i 's/width={0\.35/width={0.28/' "$1"
sed -i 's/width={0\.16/width={0.30/' "$1"
sed -i 's/width={0\.11/width={0.12/' "$1"
sed -i 's/width={0\.23/width={0.05/' "$1"
sed -i 's/nc=3/nc=3,topframe=on,bottomframe=on,roffset=1cm/' "$1"
sed -i 's/nc=2/nc=2,topframe=on,bottomframe=on/' "$1"

83
doc/table-config.txt Normal file
View File

@ -0,0 +1,83 @@
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|**Configuration |**Configuration macro (with `\def`)** |**Meaning** |**Example** |**Page** |
|key (with | | | | |
|`\crfnmsetup`)** | | | | |
+=================+===============================================+=====================+==============+==============================+
|`<type>` _is a single type_ |`page` |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`sg` |`\crfnm<type>` |Singular prefix |`{p. }` |`\at[prefixes]`{=context} |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`pl` |`\crfnm<type>s` |Plural prefix |`{pp. }` |`\at[prefixes]`{=context} |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`delimiter` |`\crfnm<type>EnumDelim` |Delimiter between |`{, }` |`\at[delimiters]`{=context} |
| | |references | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`before last |`\crfnm<type>BeforeLastInEnum` |Delimiter before the |`{ and }` |`\at[delimiters]`{=context} |
|reference` | |last reference | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`range separator`|`\crfnm<type>RangeSep` |Separator between the|`{\tt |`\at[range-sep]`{=context} |
| | |two values in a range|`{=context} | |
| | | |`}`{=context} | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`collapsable?` |`\crfnm<type>Collapsable` |Should consecutive |`yes` or `no` |`\at[collapsable]`{=context} |
| | |numbers (e.g. 2, 3, | | |
| | |4) be merged into a | | |
| | |range? | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`<type>` _is a double type_ |`pagenote` |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`subtypes |`\crfnm<type>SubtypesSep` |Separator between the|`{, }` |`\at[subtypes-sep]`{=context} |
|separator` | |two types of | | |
| | |references in a | | |
| | |double reference | | |
| | |(e.g. between the | | |
| | |page and note numbers| | |
| | |in a reference to a | | |
| | |note including the | | |
| | |page number) | | |
| | | | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`print prefix of |`\crfnm<type>PrintFirstPrefix` |Should the numbers of|`always` or |`\at[fst-pref-dbl]`{=context} |
|first subtype` | |the first subtype be |`once` | |
| | |prefixed always or | | |
| | |only for the first | | |
| | |reference in an | | |
| | |enumeration? | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`group subtypes?`|`\crfnm<type>GroupSubtypes` |Sould all the values |`yes` or `no` |`\at[group-subt]`{=context} |
| | |for each subtype be | | |
| | |printed separately? | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`order` |`\crfnm<type>Order` |Whether the subtypes |`normal` or |`\at[order]`{=context} |
| | |are printed in the |`inverted` | |
| | |same order as in the | | |
| | |name of the double | | |
| | |type | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`<type>` _is a single type; the following options apply when it is used as the second |`page` |
|subtype of a double type_ | |
| | |
| | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`formatting when |`\crfnm<type>FormatInSecond` |`{}` or a macro that |`\textbf` |`\at[fmt-sec-subt]`{=context} |
|second subtype` | |takes the prefixes | | |
| | |and numbers as its | | |
| | |argument | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`print prefix |`\crfnm<type>PrintPrefixInSecond` |Should the prefix be |`yes` or `no` |`\at[rep-pref-dbl]`{=context} |
|when second | |printed? | | |
|subtype?` | | | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`delimiter when |`\crfnm<type>EnumDelimInSecond` |Delimiter between |`{, }` |`\at[delim-sec-dbl]`{=context}|
|second subtype` | |references | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`before last |`\crfnm<type>BeforeLastInSecond` |Delimiter before the |`{ and }` |`\at[delim-sec-dbl]`{=context}|
|reference when | |last reference | | |
|second subtype` | | | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+
|`continuous |`\crfnm<type>NumberingContinuousAcrossDocument`|Is the numbering for |`yes` or `no` |`\at[numb-contin]`{=context} |
|numbering?` | |this type continuous | | |
| | |(i.e. not reset at | | |
| | |every | | |
| | |page/chapter/etc.)? | | |
+-----------------+-----------------------------------------------+---------------------+--------------+------------------------------+

View File

@ -18,6 +18,11 @@ check_files(){
check_files
cd doc
make crossrefenum.pdf
if [[ $? != 0 ]] ; then cd - ; exit 1 ; fi
cd -
if [[ -a crossrefenum.zip ]] ; then rm crossrefenum.zip ; fi
mkdir crossrefenum
cd crossrefenum
@ -32,7 +37,8 @@ for file in crossrefenum.md crossrefenum.pdf fixes.lua LICENSE_FDL_1-3.md Makefi
done
cd ../test
for file in config-crossrefenum.tex config-formats.tex data-common.tex data-lines.tex data-reledmac.tex format-specific-defs.tex main-test_context.pdf main-test_latex.pdf main-test.tex Makefile validated-output ; do
cd ../../test/ && make check ; cd -
for file in config-crossrefenum.tex config-formats.tex data-common.tex data-lines.tex data-reledmac.tex format-specific-defs.tex main-test.pdf main-test.tex Makefile validated-output ; do
ln -s ../../test/$file $file
done
@ -42,5 +48,4 @@ for file in crossrefenum.sty crossrefenum.tex t-crossrefenum.tex ; do
done
cd ../..
7z a -l crossrefenum.zip crossrefenum
rm -r --interactive=never crossrefenum
7z a crossrefenum.zip crossrefenum && rm -r --interactive=never crossrefenum

View File

@ -4,10 +4,10 @@ ALL=main-test.tex data-common.tex data-reledmac.tex config-formats.tex config-cr
define MAKE_BOXES_LIST
sed -i 's/%\\tracingoutput/\\tracingoutput/' $<
-xelatex main-test.tex
-lualatex main-test.tex
sed -i 's/^\\tracingoutput/%\\tracingoutput/' $<
full_boxes_list="$$(grep -E '^\.+\\TU' main-test.log)"; \
i_test_result_end="$$(( $$(grep -Fn '....\TU/lmr/m/sc/10 Capitulus' <<< "$$full_boxes_list" | head -n 1 | cut -d ':' -f 1) - 1))"; \
i_test_result_end="$$(( $$(grep -Fn '....\TU/lmr/m/sc/10 C' <<< "$$full_boxes_list" | head -n 1 | cut -d ':' -f 1) - 1))"; \
sed -n 1,$${i_test_result_end}p <<< "$$full_boxes_list" > $@
endef
@ -15,12 +15,12 @@ clean:
-rm main-test.{aux,log,1,2,fdb_latexmk,fls,xdv,tuc}
test: clean $(ALL)
latexmk -xelatex main-test.tex
latexmk -lualatex main-test.tex
log: $(ALL)
sed -i 's/%\\tracingcommands/\\tracingcommands/' $<
sed -i 's/%\\tracingmacros/\\tracingmacros/' $<
-xelatex main-test.tex
-lualatex main-test.tex
sed -i 's/^\\tracingcommands/%\\tracingcommands/' $<
sed -i 's/^\\tracingmacros/%\\tracingmacros/' $<

View File

@ -1,6 +1,5 @@
\crfnm@case[\fmtname]
\crfnm@latex: {
\documentclass{article}
\usepackage[a5paper]{geometry}
\usepackage{setspace}
\doublespacing

View File

@ -6,6 +6,7 @@
\def\crfnmresetpage{\setnumber[userpage][1]}
\def\smaller{\setupbodyfont[script]}
\let\crfnmsc\sc
\def\textit##1{{\it ##1}}
}
\crfnm@latex: {
\def\crfnmlbl##1{{\bf [##1]}\label{##1}}

View File

@ -1,3 +1,10 @@
\long\def\iflatex#1{%
\expandafter\ifx\csname usepackage\endcsname\relax\else #1\fi
}
\long\def\ifcontext#1{%
\expandafter\ifx\csname contextformat\endcsname\relax\else #1\fi
}
\iflatex{\documentclass{article}}
\input ../tex/crossrefenum
\crfnmOriginalCatcodeAt=\catcode`\@
\catcode`\@=11
@ -14,14 +21,6 @@
\def\withvisiblespace{\tt}
\long\def\iflatex#1{%
\expandafter\ifx\csname usepackage\endcsname\relax\else #1\fi
}
\long\def\ifcontext#1{%
\expandafter\ifx\csname contextformat\endcsname\relax\else #1\fi
}
% TODO : verser dans crossrefenum.tex et commenter le code dans le README
\catcode`\@=11
\ifcontext{
\def\crfnm@line{Line}
@ -48,6 +47,7 @@
\def\crfnmtestdesc{#1}
\def\crfnmempty{}
\ifx\crfnmtestdesc\crfnmempty\else
\vskip2.5\bigskipamount
\vbox{%
\lineskiplimit=10000pt\lineskip=1ex
\parskip=2ex
@ -56,7 +56,7 @@
\everypar={\leftskip=1em}
\raggedright Enumeration: \crfnmTypesetEnumArg#2{crfnmEnumArgEnd}
\raggedright Enumeration: \allowbreak{\tt\detokenize{#2}}
Reference type: {\tt #3}
@ -65,22 +65,12 @@
Result: \hbox to 1.3em{}{\withvisiblespace [\crossrefenum[#3][#4]{#2}]}
}%
\vskip2.5\bigskipamount
\fi
}
\def\crfnmEnumArgEnd{crfnmEnumArgEnd}
\long\def\crfnmheader#1{\vskip3\bigskipamount{\crfnmsc #1}\par\nobreak}
\def\crfnmTypesetEnumArg#1{%
\def\crfnmTheArg{#1}%
\ifx\crfnmTheArg\crfnmEnumArgEnd\else
\allowbreak{\tt\detokenize{{#1}}}\expandafter\crfnmTypesetEnumArg
\fi
}
\long\def\crfnmheader#1{{\crfnmsc #1}\nobreak\vglue\baselineskip}
\def\crfnmverbatim#1#2{{\tt\detokenize{#1}}#2}
\def\crfnmverbatim#1{{\tt\detokenize{#1}}}
\iflatex{
\begin{document}
@ -99,7 +89,7 @@
{}
{page}
{withprefix}
{p. }
{}
\crfnmtestenum{One single page}
{{matthaeus-14}}
@ -433,6 +423,94 @@
}
\vfill\penalty-10000
\crfnmheader{With a comma-delimited list of references instead of a list of groups}
\crfnmtestenum{One single page without an inner group}
{matthaeus-14}
{page}
{withprefix}
{p. 2}
\crfnmtestenum{Three references without spaces}
{matthaeus-14,matthaeus-025,matthaeus-0223}
{page}
{withprefix}
{pp. 2, 4 and 6}
\crfnmtestenum{Three references with spaces}
{matthaeus-14, matthaeus-025, matthaeus-0223}
{page}
{withprefix}
{pp. 2, 4 and 6}
\crfnmtestenum{With a double type}
{note-Aminadab-undecim, note-generationes-quis, note-regem-Theman}
{pagenote}
{withprefix}
{p. 1, n. 1, p. 2, n. 3 and p. 4, n. 3}
\crfnmheader{Key-value configuration interface}
Heavily modified setup for {\tt page}, {\tt note} and {\tt pagenote} with \crfnmverbatim{\crfnmsetup}
\crfnmsetup[page]{
sg = {page },
pl = {pages },
delimiter = {; },
before last reference = { AND },
range separator = { to },
collapsable? = yes
}
\crfnmsetup[note]{
sg = {note },
pl = {notes },
print prefix when second subtype? = no,
delimiter when second subtype = +,
before last reference when second subtype = { And },
formatting when second subtype = \textit % single-arg macro
}
\crfnmsetup[pagenote]{
delimiter = {; },
before last reference = { AND },
range separator = { to },
subtypes separator = { in },
print prefix of first subtype = once,
group subtypes? = no,
continuous numbering? = no
}
\crfnmtestenum{Simple type}
{matthaeus-14, matthaeus-025, matthaeus-0223}
{page}
{withprefix}
{pages 2; 4 AND 6}
\crfnmtestenum{Simple type with a range}
{{matthaeus-2 to matthaeus-15}{matthaeus-16}}
{page}
{withprefix}
{pages 1 to 2}
\crfnmtestenum{Double type}
{note-Aminadab-undecim, note-generationes-quis, note-congregans-conteram, note-Israhel-mittam, note-regem-Theman}
{pagenote}
{withprefix}
{pages 1 in \textit{1}; 2 in \textit{3} AND \textit{4} in \textit{1+2 And 3}}
\crfnmsetup[page]{
collapsable? = no
}
\crfnmtestenum{Pages are not collapsable anymore!}
{{matthaeus-2}{matthaeus-15}{matthaeus-22}{matthaeus-025}}
{page}
{withprefix}
{pages 1; 2; 3 AND 4}
\iflatex{\end{english}}
\ifcontext{
\language[latin]
@ -449,8 +527,6 @@
\input data-lines
\ifcontext{\stoptext}
\iflatex{
\def\crfnmtheend{\end{document}}
\expandafter\crfnmtheend
}
\ifcontext{\let\crfnmtheend\stoptext}
\iflatex{\def\crfnmtheend{\end{document}}}
\crfnmtheend

File diff suppressed because it is too large Load Diff

View File

@ -2,10 +2,10 @@
\def\crfnmName{crossrefenum}
\def\crfnmShortDesc{Smart typesetting of enumerated cross-references for various TeX formats}
\def\crfnmAuthor{Bastien Dumont}
\def\crfnmDate{2023/02/20}
\def\crfnmVersion{1.0.1}
\def\crfnmDate{2025/08/07}
\def\crfnmVersion{1.2}
%
% Copyright 2022 by Bastien Dumont (bastien.dumont@posteo.net)
% Copyright 2022-2025 by Bastien Dumont (bastien.dumont@posteo.net)
%
% crossrefenum.tex is free software: you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
@ -410,6 +410,51 @@
%%% Initialization: Auxiliary macros related to the data structure of \crossrefenum %%%
% Trivial low-level macros
\def\crfnm@appendToToks#1#2{#1=\expandafter{\the#1#2}}
\expandafter\def\expandafter\crfnm@gobspace\space{}
\def\crfnm@lettok#1#2{\let#1= #2}
\crfnm@lettok\crfnm@space{ }
\def\crfnm@gobbleFirst#1{}
% Lists of groups
\def\crfnm@ifIsList[#1]#2#3{%
\expandafter\futurelet\expandafter\crfnm@nextToken
\expandafter\crfnm@ifIsBgroup #1\endofcheck{#2}{#3}%
}
\def\crfnm@ifIsBgroup#1\endofcheck#2#3{%
% \crfnm@nextToken is the first token in the #1 of \crfnm@ifIsList.
% All the #1 of \crfnm@ifIsList is stored here in #1 and discarded.
\ifx\crfnm@nextToken\bgroup #2\else #3\fi
}
\def\crfnm@newListFrom[#1][#2] -> #3{%
% #1 is either a list or a reference.
% #2 is the reference appended to #1.
% #3 is the control sequence which the resulting list will be bound to.
\crfnm@ifIsList[#1]{%
\edef#3{#1{#2}}%
}{%
\edef#3{{#1}{#2}}%
}%
}
\def\crfnm@addToList[#1][#2]{\crfnm@newListFrom[#1][#2] -> #1}
\def\crfnm@declareType[#1][#2]{%
% #1 is "simple" or "double", #2 is the type
\expandafter\crfnm@addToList\expandafter[\csname crfnm@#1RefTypes\endcsname][#2]%
\crfnm@addToList[\crfnm@supportedTypes][#2]%
}
\def\crfnm@replaceFirstInList[#1]#2{%
% #1 is a token, #2 is a list of tokens
{#1}\crfnm@gobbleFirst #2%
}
% crossrefenum-specific
\edef\crfnm@simpleRefTypes{{\crfnm@page}{\crfnm@note}{\crfnm@line}{\crfnm@edpage}{\crfnm@edline}}
\edef\crfnm@doubleRefTypes{{\crfnm@pagenote}{\crfnm@pageline}{\crfnm@edpageline}}
\edef\crfnm@customizableDefaultConfig{{Collapsable}{EnumDelim}{EnumDelimInSecond}{BeforeLastInEnum}{BeforeLastInSecond}{RangeSep}}
@ -459,36 +504,41 @@
}%
}
\def\crfnm@ifIsList[#1]#2#3{%
\expandafter\futurelet\expandafter\crfnm@nextToken
\expandafter\crfnm@ifIsBgroup #1\endofcheck{#2}{#3}%
}
\def\crfnm@ifIsBgroup#1\endofcheck#2#3{%
% \crfnm@nextToken is the first token in the #1 of \crfnm@ifIsList.
% All the #1 of \crfnm@ifIsList is stored here in #1 and discarded.
\ifx\crfnm@nextToken\bgroup #2\else #3\fi
}
\def\crfnm@newListFrom[#1][#2] -> #3{%
% #1 is either a list or a reference.
% #2 is a reference.
% #2 is appended to #1.
% #3 is the control sequence which the resulting list will be bound to.
\crfnm@ifIsList[#1]{%
\edef#3{#1{#2}}%
}{%
\edef#3{{#1}{#2}}%
%%% Initialization: Key-value configuration interface %%%
\expandafter\ifx\csname crfnmNoKV\endcsname\relax
\crfnm@case[\fmtname]
\crfnm@context: {\usemodule[expkv-def]}
\crfnm@latex: {\usepackage{expkv-def}}
\fmtname: {\input{expkv-def}}
\crfnm@endCases
\def\crfnmsetup[#1]#2{%
% #1 = a reference type or "default"
\ekvdefinekeys{crfnm@type@#1}{
code sg = \expandafter\def\csname crfnm\crfnm@capitalize #1\endcsname{##1},
code pl = \expandafter\def\csname crfnm\crfnm@capitalize #1s\endcsname{##1},
code delimiter = \expandafter\def\csname crfnm\crfnm@capitalize #1EnumDelim\endcsname{##1},
code before last reference = \expandafter\def\csname crfnm\crfnm@capitalize #1BeforeLastInEnum\endcsname{##1},
code range separator = \expandafter\def\csname crfnm\crfnm@capitalize #1RangeSep\endcsname{##1},
code collapsable? = \expandafter\def\csname crfnm\crfnm@capitalize #1Collapsable\endcsname{##1},
code subtypes separator = \expandafter\def\csname crfnm\crfnm@capitalize #1SubtypesSep\endcsname{##1},
code print prefix of first subtype = \expandafter\def\csname crfnm\crfnm@capitalize #1PrintFirstPrefix\endcsname{##1},
code formatting when second subtype = \expandafter\def\csname crfnm\crfnm@capitalize #1FormatInSecond\endcsname####1{##1{####1}},
code print prefix when second subtype? = \expandafter\def\csname crfnm\crfnm@capitalize #1PrintPrefixInSecond\endcsname{##1},
code delimiter when second subtype = \expandafter\def\csname crfnm\crfnm@capitalize #1EnumDelimInSecond\endcsname{##1},
code before last reference when second subtype = \expandafter\def\csname crfnm\crfnm@capitalize #1BeforeLastInSecond\endcsname{##1},
code group subtypes? = \expandafter\def\csname crfnm\crfnm@capitalize #1GroupSubtypes\endcsname{##1},
code continuous numbering? = \expandafter\def\csname crfnm\crfnm@capitalize #1NumberingContinuousAcrossDocument\endcsname{##1},
code order = \expandafter\def\csname crfnm\crfnm@capitalize #1Order\endcsname{##1}
}%
\ekvset{crfnm@type@#1}{#2}%
}
\def\crfnm@replaceFirstInList[#1]#2{%
% #1 is a token, #2 is a list of tokens
{#1}\crfnm@gobbleFirst #2%
}
\def\crfnm@gobbleFirst#1{}
\fi
%%% Initialization: Default configuration %%%
@ -600,7 +650,8 @@
{%
% Initializes the environment for this invocation,
% then passes the enumeration to the parsing
% and formatting macro \crfnm@formatEnum.
% and formatting macro \crfnm@formatEnum
% through \crfnm@getAndProcessList.
\global\advance\crfnm@ienum by 1
% The reference type is capitalized so that it can be used
% to refer to macro names typed in camelCase
@ -628,9 +679,10 @@
\edef\crfnm@printedRefsNb@previousPass{%
\crfnm@getPrintedRefsNb@previousPass
}%
% The following macro will process sequentially
% all references in the enumeration.
\expandafter\crfnm@formatEnum#3{crfnm@enumend}%
\edef\crfnm@thearg{#3}%
\ifx\crfnm@thearg\crfnm@empty\else
\expandafter\crfnm@getAndProcessList\expandafter{\crfnm@thearg}%
\fi
}%
}
@ -737,13 +789,57 @@
}
\crfnm@endCases
% If the last argument of \crossrefenum is a list of groups,
% pass it directly to \crfnm@formatEnum.
% Else, it is a comma-delimited list of strings (with optional leading spaces)
% to be transformed to a list of groups suitable for \crfnm@formatEnum.
\def\crfnm@getAndProcessList#1{%
\crfnm@getListDispatcher #1\crfnm@enumend
}
\def\crfnm@getListDispatcher{\futurelet\crfnm@nexttok\crfnm@getList@dispatcher}
\def\crfnm@getList@dispatcher{%
\ifx\crfnm@nexttok\bgroup
\expandafter\crfnm@formatEnum
\else
\expandafter\crfnm@commaListToGroups
\fi
}
\newtoks\crfnm@listAsGroups
\def\crfnm@commaListToGroups#1\crfnm@enumend{%
\crfnm@listAsGroups={}%
\crfnm@commaList@toGroups#1,\crfnm@end,%
}
\def\crfnm@commaList@toGroups#1,{%
\edef\crfnm@thearg{#1}%
\ifx\crfnm@thearg\crfnm@end
\def\crfnm@todo{%
\expandafter\crfnm@formatEnum\the\crfnm@listAsGroups\crfnm@enumend
}%
\else
\crfnm@appendToToks\crfnm@listAsGroups{{#1}}%
\def\crfnm@todo{\futurelet\crfnm@nexttok\crfnm@nextItemToGroup}%
\fi
\crfnm@todo
}
\def\crfnm@nextItemToGroup{%
\ifx\crfnm@nexttok\crfnm@space
\def\crfnm@todo{\expandafter\crfnm@commaList@toGroups\crfnm@gobspace}%
\else
\let\crfnm@todo\crfnm@commaList@toGroups
\fi
\crfnm@todo
}
%%% \crossrefenum: Processing the individual references in the enumeration %%%
\def\crfnm@formatEnum#1{%
% #1 is a string consisting of either:
% * <label>
% * <label1> to <label2>
% * crfnm@enumend
% * \crfnm@enumend
\crfnm@ifIsBeginOfEnum{%
\crfnm@setCurrentRef{#1}%
% We typeset the prefix at the beginning of the enumeration
@ -775,10 +871,10 @@
\def\crfnm@setCurrentRef#1{%
\crfnm@ifIsDoubleRef{%
\def\crfnm@currentPrimary{#1}%
\def\crfnm@currentSecondary{#1}%
\edef\crfnm@currentPrimary{#1}%
\edef\crfnm@currentSecondary{#1}%
}{%
\def\crfnm@current{#1}%
\edef\crfnm@current{#1}%
}%
}
@ -838,7 +934,7 @@
% Works in LaTeX because warnings are sent via \immediate\write.
% It should also work in ConTeXt because it writes the logs through
% a Lua call, not \write.
\def\crfnm@tested{#1}%
\edef\crfnm@tested{#1}%
\ifx\crfnm@tested\crfnm@enumend\else
\setbox0=\hbox{\crfnm@simulateTypesetting{#1}}%
\fi
@ -873,11 +969,11 @@
\crfnm@ifIsDoubleRef{%
\let\crfnm@precedingPrimary\crfnm@currentPrimary
\let\crfnm@precedingSecondary\crfnm@currentSecondary
\def\crfnm@currentPrimary{#1}%
\def\crfnm@currentSecondary{#1}%
\edef\crfnm@currentPrimary{#1}%
\edef\crfnm@currentSecondary{#1}%
}{%
\let\crfnm@preceding\crfnm@current
\def\crfnm@current{#1}%
\edef\crfnm@current{#1}%
}%
}

View File

@ -5,7 +5,7 @@
%D subtitle=Smart typesetting of enumerated cross-references for various TeX formats,
%D author=Bastien Dumont,
%D date=2022/11/11,
%D url=%TODO,
%D url=https://ctan.org/tex-archive/macros/generic/crossrefenum/tex/t-crossrefenum.tex,
%D copyright=Bastien Dumont,
%D license=GNU Public License v. 3.0 or higher]