diff options
author | Norbert Preining <norbert@preining.info> | 2021-07-22 03:01:06 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-07-22 03:01:06 +0000 |
commit | c43a0b49bea6195daa6423809f4339d538b5c8d9 (patch) | |
tree | 88ebc40586174a8ad651baa8020266c4070f39e3 /macros/generic | |
parent | d06b4118c72d0c81fc0760e24add55e808471dbc (diff) |
CTAN sync 202107220301
Diffstat (limited to 'macros/generic')
-rw-r--r-- | macros/generic/texdimens/README.md | 258 | ||||
-rw-r--r-- | macros/generic/texdimens/texdimens.sty | 2 | ||||
-rw-r--r-- | macros/generic/texdimens/texdimens.tex | 308 | ||||
-rw-r--r-- | macros/generic/xstring/README | 4 | ||||
-rw-r--r-- | macros/generic/xstring/test_etex.pdf | bin | 99780 -> 99781 bytes | |||
-rw-r--r-- | macros/generic/xstring/test_latex.pdf | bin | 150611 -> 155263 bytes | |||
-rw-r--r-- | macros/generic/xstring/xstring-en.pdf | bin | 187648 -> 199536 bytes | |||
-rw-r--r-- | macros/generic/xstring/xstring-en.tex | 2 | ||||
-rw-r--r-- | macros/generic/xstring/xstring-fr.pdf | bin | 201920 -> 215317 bytes | |||
-rw-r--r-- | macros/generic/xstring/xstring-fr.tex | 2 | ||||
-rw-r--r-- | macros/generic/xstring/xstring.tex | 343 |
11 files changed, 527 insertions, 392 deletions
diff --git a/macros/generic/texdimens/README.md b/macros/generic/texdimens/README.md index 4f028fe689..d574ae2ae6 100644 --- a/macros/generic/texdimens/README.md +++ b/macros/generic/texdimens/README.md @@ -10,7 +10,7 @@ LPPL 1.3c. See file LICENSE.md. Development: https://github.com/jfbu/texdimens -Release: `0.9delta 2021/07/15` +Release: `0.9 2021/07/21` ## Aim of this package @@ -46,24 +46,24 @@ of one TeX point `1pt`, or rather `1pt` is represented internally as `65536`. If `\foo` is a dimen register: -- `\number\foo` produces the integer `N` such as `\foo` is the same as `N sp`, +- `\number\foo` produces the integer `N` such as `\foo` is the same as `Nsp`, - inside `\numexpr`, `\foo` is replaced by `N`, - `\the\foo` produces a decimal `D` (with at most five places) followed -with `pt` (catcode 12 tokens) and this output `D pt` can serve as input +with `pt` (catcode 12 tokens) and this output `Dpt` can serve as input in a dimen assignment to produce the same dimension as `\foo`. One can also use the catcode 11 characters `pt` for this. Digits and decimal mark must have their standard catcode 12. -When TeX encounters a dimen denotation of the type `D pt` it will +When TeX encounters a dimen denotation of the type `Dpt` it will compute `N` in a way equivalent to `N = round(65536 D)` where ties are rounded away from zero. Only 17 decimal places of `D` are kept as it can be shown that going beyond can not change the result. -When `\foo` has been assigned as `D pt`, `\the\foo` will produce some -`E pt` where `E` is not necessarily the same as `D`. But it is guaranteed -that `E pt` defines the same dimension as `D pt̀`. +When `\foo` has been assigned as `Dpt`, `\the\foo` will produce some +`Ept` where `E` is not necessarily the same as `D`. But it is guaranteed +that `Ept` defines the same dimension as `Dpt̀`. ## Further units known to TeX on input @@ -100,8 +100,8 @@ among those listed above, it first handles `U` as with the `pt` unit. This means that it computes `N = round(65536*U)`. It then multiplies this `N` by the conversion factor `phi` and truncates towards zero the mathematically exact result to obtain an integer `T`: -`T=trunc(N*phi)`. The assignment `U uu` is concluded by defining the -value of the dimension to be `T sp`. +`T=trunc(N*phi)`. The assignment `Uuu` is concluded by defining the +value of the dimension to be `Tsp`. Attention that although the mnemotic is `phi=1uu/1pt`, this formula definitely does not apply with numerator and denominator interpreted as @@ -129,7 +129,7 @@ between attainable dimensions is `72--73sp` for the `in` and `28--29sp` for the `cm`, and as `1in` differs internally from `2.54cm` by only `12sp` (see below the `xintsession` verbatim) it is impossible to adjust either the `in` side or the `cm` side to obtain equality. See in the -[TODO] section the closest dimension attainable both via `in` and via +[Extras?] section the closest dimension attainable both via `in` and via `cm`. In particular `1in==2.54cm` is **false** in TeX, but it is true that @@ -152,19 +152,19 @@ In particular `1in==2.54cm` is **false** in TeX, but it is true that other units the maximal attainable dimensions in `sp` unit are given in the middle column of the next table. - maximal allowed the corresponding minimal TeX dimen denotation - (with 5 places) maximal attainable dim. causing "Dimension too large" - --------------- -------------------------- -------------------------- - 16383.99999 pt 1073741823 sp (=\maxdimen) 16383.99999237060546875 pt - 16322.78954 bp 1073741823 sp (=\maxdimen) 16322.78954315185546875 bp - 15355.51532 nd 1073741823 sp (=\maxdimen) 15355.51532745361328125 nd - 15312.02584 dd 1073741822 sp 15312.02584075927734375 dd - 5758.31742 mm 1073741822 sp 5758.31742095947265625 mm - 1365.33333 pc 1073741820 sp 1365.33333587646484375 pc - 1279.62627 nc 1073741814 sp 1279.62627410888671875 nc - 1276.00215 cc 1073741821 sp 1276.00215911865234375 cc - 575.83174 cm 1073741822 sp 575.83174896240234375 cm - 226.70540 in 1073741768 sp 226.70540618896484375 in + maximal allowed the corresponding minimal TeX dimen denotation + (with 5 places) maximal attainable dim. causing "Dimension too large" + --------------- ------------------------- -------------------------- + 16383.99999pt 1073741823sp (=\maxdimen) 16383.99999237060546875pt + 16322.78954bp 1073741823sp (=\maxdimen) 16322.78954315185546875bp + 15355.51532nd 1073741823sp (=\maxdimen) 15355.51532745361328125nd + 15312.02584dd 1073741822sp 15312.02584075927734375dd + 5758.31742mm 1073741822sp 5758.31742095947265625mm + 1365.33333pc 1073741820sp 1365.33333587646484375pc + 1279.62627nc 1073741814sp 1279.62627410888671875nc + 1276.00215cc 1073741821sp 1276.00215911865234375cc + 575.83174cm 1073741822sp 575.83174896240234375cm + 226.70540in 1073741768sp 226.70540618896484375in Perhaps for these various peculiarities with dimensional units, TeX does not provide an output facility for them similar to what `\the` achieves for @@ -173,11 +173,11 @@ the `pt`. ## Macros of this package The macros defined by the package are expandable, and will expand -completely in an `\edef`, or in a `\dimexpr...\relax` construc. +completely in an `\edef`, or in a `\dimexpr...\relax` construct. As they parse their inputs via `\dimexpr` they can be nested (with -suitable postfix dimension unit added to inner macro). +the suitable dimension unit added as postfix to nested macro). -Apart for the `\texdimin<uu>up` in case of a negative input, they will +Apart from the `\texdimen<uu>up` in case of a negative input, they will even expand completely under f-expansion. Negative dimensions behave as if replaced by their absolute value, then @@ -187,67 +187,67 @@ at last step the sign (if result is not zero) is applied (so "down" means 1. For input `X` equal to (or sufficiently close to) `\maxdimen` and those units `uu` for which `\maxdimen` is not exactly representable (i.e. all units except `pt`, `bp` and `nd`), the output `D` of the - "up" macros `\texdimin<uu>up{X}`, if used as `Duu` in a dimension + "up" macros `\texdimen<uu>up{X}`, if used as `Duu` in a dimension assignment or expression, will (naturally) trigger a "Dimension too large" error. 2. For `dd`, `nc` and `in`, and input `X` equal to (or sufficiently - close to) `\maxdimen` it turns out that `\texdimin<uu>{X}` produces + close to) `\maxdimen` it turns out that `\texdimen<uu>{X}` produces an output `D` such that `Duu` is the first "virtually attainable" TeX dimension *beyond* `\maxdimen`. Hence `Duu` will trigger on use "Dimension too large error". 3. Again for the `dd`, `nc` and `in` units, both the "down" and "up" macros will trigger "Dimension too large" during their execution if used - with an input equal to (or sufficiently close to `\maxdimen`. + with an input equal to (or sufficiently close to) `\maxdimen`. -`\texdiminpt{<dim. expr.>}` +`\texdimenpt{<dim. expr.>}` > Does `\the\dimexpr <dim. expr.> \relax` then removes the `pt`. -`\texdiminbp{<dim. expr.>}` +`\texdimenbp{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D bp` +> Produces a decimal (with up to five decimal places) `D` such that `Dbp` > represents the dimension exactly if possible. If not possible it > will differ by `1sp` from the original dimension, but it is not > known in advance if it will be above or below. > `\maxdimen` on input produces `16322.78954` and indeed is realized as `16322.78954bp`. -`\texdiminbpdown{<dim. expr.>}` +`\texdimenbpdown{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D bp` +> Produces a decimal (with up to five decimal places) `D` such that `Dbp` > represents the dimension exactly if possible. If not possible it > will be smaller by `1sp` from the original dimension. -`\texdiminbpup{<dim. expr.>}` +`\texdimenbpup{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D bp` +> Produces a decimal (with up to five decimal places) `D` such that `Dbp` > represents the dimension exactly if possible. If not possible it > will be larger by `1sp` from the original dimension. -`\texdiminnd{<dim. expr.>}` +`\texdimennd{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D nd` +> Produces a decimal (with up to five decimal places) `D` such that `Dnd` > represents the dimension exactly if possible. If not possible it > will differ by `1sp` from the original dimension, but it is not > known in advance if it will be above or below. > `\maxdimen` on input produces `15355.51532` and indeed is realized as `15355.51532nd`. -`\texdiminnddown{<dim. expr.>}` +`\texdimennddown{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D nd` +> Produces a decimal (with up to five decimal places) `D` such that `Dnd` > represents the dimension exactly if possible. If not possible it > will be smaller by `1sp` from the original dimension. -`\texdiminndup{<dim. expr.>}` +`\texdimenndup{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D nd` +> Produces a decimal (with up to five decimal places) `D` such that `Dnd` > represents the dimension exactly if possible. If not possible it > will be larger by `1sp` from the original dimension. -`\texdimindd{<dim. expr.>}` +`\texdimendd{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D dd` +> Produces a decimal (with up to five decimal places) `D` such that `Ddd` > represents the dimension exactly if possible. If not possible it > will differ by `1sp` from the original dimension, but it is not > known in advance if it will be above or below. @@ -256,21 +256,21 @@ at last step the sign (if result is not zero) is applied (so "down" means > will trigger "Dimension too large" error. > `\maxdimen-1sp` is attainable via `15312.02584dd`. -`\texdimindddown{<dim. expr.>}` +`\texdimendddown{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D dd` +> Produces a decimal (with up to five decimal places) `D` such that `Ddd` > represents the dimension exactly if possible. If not possible it > will be smaller by `1sp` from the original dimension. -`\texdiminddup{<dim. expr.>}` +`\texdimenddup{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D dd` +> Produces a decimal (with up to five decimal places) `D` such that `Ddd` > represents the dimension exactly if possible. If not possible it > will be larger by `1sp` from the original dimension. -`\texdiminmm{<dim. expr.>}` +`\texdimenmm{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D mm` +> Produces a decimal (with up to five decimal places) `D` such that `Dmm` > represents the dimension exactly if possible. If not possible it > will either be the closest from below or from above, but it is not > known in advance which one (and it is not known if the other choice @@ -279,21 +279,21 @@ at last step the sign (if result is not zero) is applied (so "down" means > `\maxdimen` as input produces on output `5758.31741` and indeed the > maximal attainable dimension is `5758.31741mm` (`1073741822sp`). -`\texdiminmmdown{<dim. expr.>}` +`\texdimenmmdown{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D mm` +> Produces a decimal (with up to five decimal places) `D` such that `Dmm` > represents the dimension exactly if possible. If not possible it > will be largest representable dimension smaller than the original one. -`\texdiminmmup{<dim. expr.>}` +`\texdimenmmup{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D mm` +> Produces a decimal (with up to five decimal places) `D` such that `Dmm` > represents the dimension exactly if possible. If not possible it > will be smallest representable dimension larger than the original one. -`\texdiminpc{<dim. expr.>}` +`\texdimenpc{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D pc` +> Produces a decimal (with up to five decimal places) `D` such that `Dpc` > represents the dimension exactly if possible. If not possible it > will be the closest representable one (in case of tie, the approximant > from above is chosen). @@ -301,21 +301,21 @@ at last step the sign (if result is not zero) is applied (so "down" means > `\maxdimen` as input produces on output `1365.33333` and indeed the > maximal attainable dimension is `1365.33333pc` (`1073741820sp`). -`\texdiminpcdown{<dim. expr.>}` +`\texdimenpcdown{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D pc` +> Produces a decimal (with up to five decimal places) `D` such that `Dpc` > represents the dimension exactly if possible. If not possible it > will be largest representable dimension smaller than the original one. -`\texdiminpcup{<dim. expr.>}` +`\texdimenpcup{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D pc` +> Produces a decimal (with up to five decimal places) `D` such that `Dpc` > represents the dimension exactly if possible. If not possible it > will be smallest representable dimension larger than the original one. -`\texdiminnc{<dim. expr.>}` +`\texdimennc{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D nc` +> Produces a decimal (with up to five decimal places) `D` such that `Dnc` > represents the dimension exactly if possible. If not possible it > will either be the closest from below or from above, but it is not > known in advance which one (and it is not known if the other choice @@ -325,21 +325,21 @@ at last step the sign (if result is not zero) is applied (so "down" means > will trigger "Dimension too large" error. > `\maxdimen-9sp` is attainable via `1279.62627nc`. -`\texdiminncdown{<dim. expr.>}` +`\texdimenncdown{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D nc` +> Produces a decimal (with up to five decimal places) `D` such that `Dnc` > represents the dimension exactly if possible. If not possible it > will be largest representable dimension smaller than the original one. -`\texdiminncup{<dim. expr.>}` +`\texdimenncup{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D nc` +> Produces a decimal (with up to five decimal places) `D` such that `Dnc` > represents the dimension exactly if possible. If not possible it > will be smallest representable dimension larger than the original one. -`\texdimincc{<dim. expr.>}` +`\texdimencc{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D cc` +> Produces a decimal (with up to five decimal places) `D` such that `Dcc` > represents the dimension exactly if possible. If not possible it > will either be the closest from below or from above, but it is not > known in advance which one (and it is not known if the other choice @@ -348,21 +348,21 @@ at last step the sign (if result is not zero) is applied (so "down" means > `\maxdimen` as input produces on output `1276.00215` and indeed the > maximal attainable dimension is `1276.00215cc` (`1073741821sp`). -`\texdiminccdown{<dim. expr.>}` +`\texdimenccdown{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D cc` +> Produces a decimal (with up to five decimal places) `D` such that `Dcc` > represents the dimension exactly if possible. If not possible it > will be largest representable dimension smaller than the original one. -`\texdiminccup{<dim. expr.>}` +`\texdimenccup{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D cc` +> Produces a decimal (with up to five decimal places) `D` such that `Dcc` > represents the dimension exactly if possible. If not possible it > will be smallest representable dimension larger than the original one. -`\texdimincm{<dim. expr.>}` +`\texdimencm{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D cm` +> Produces a decimal (with up to five decimal places) `D` such that `Dcm` > represents the dimension exactly if possible. If not possible it > will either be the closest from below or from above, but it is not > known in advance which one (and it is not known if the other choice @@ -371,21 +371,21 @@ at last step the sign (if result is not zero) is applied (so "down" means > `\maxdimen` as input produces on output `575.83174` and indeed the > maximal attainable dimension is `575.83174cm` (`1073741822sp`). -`\texdimincmdown{<dim. expr.>}` +`\texdimencmdown{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D cm` +> Produces a decimal (with up to five decimal places) `D` such that `Dcm` > represents the dimension exactly if possible. If not possible it > will be largest representable dimension smaller than the original one. -`\texdimincmup{<dim. expr.>}` +`\texdimencmup{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D cm` +> Produces a decimal (with up to five decimal places) `D` such that `Dcm` > represents the dimension exactly if possible. If not possible it > will be smallest representable dimension larger than the original one. -`\texdiminin{<dim. expr.>}` +`\texdimenin{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D in` +> Produces a decimal (with up to five decimal places) `D` such that `Din` > represents the dimension exactly if possible. If not possible it > will either be the closest from below or from above, but it is not > known in advance which one (and it is not known if the other choice @@ -395,18 +395,54 @@ at last step the sign (if result is not zero) is applied (so "down" means > will trigger "Dimension too large" error. > `\maxdimen-55sp` is maximal attainable dimension (via `226.7054in`). -`\texdiminindown{<dim. expr.>}` +`\texdimenindown{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D in` +> Produces a decimal (with up to five decimal places) `D` such that `Din` > represents the dimension exactly if possible. If not possible it > will be largest representable dimension smaller than the original one. -`\texdimininup{<dim. expr.>}` +`\texdimeninup{<dim. expr.>}` -> Produces a decimal (with up to five decimal places) `D` such that `D in` +> Produces a decimal (with up to five decimal places) `D` such that `Din` > represents the dimension exactly if possible. If not possible it > will be smallest representable dimension larger than the original one. +`\texdimenbothcmin{<dim. expr.>}` (new with `0.9dev`) + +> Produces a decimal (with up to five decimal places) `D` such that `Din` +> is the largest dimension smaller than the original one and +> exactly representable both in the `in` and `cm` units. + +`\texdimenbothincm{<dim. expr.>}` (new with `0.9dev`) + +> Produces a decimal (with up to five decimal places) `D` such that `Dcm` +> is the largest dimension smaller than the original one and +> exactly representable both in the `in` and `cm` units. It thus represents +> the same dimension as `\texdimenbothcmin{<dim. expr.>}in`. + +`\texdimenbothcminpt{<dim. expr.>}` (new with `0.9dev`) + +> Produces a decimal (with up to five decimal places) `D` such that `Dpt` +> is the largest dimension smaller than the original one and +> exactly representable both in the `in` and `cm` units. It thus represents +> the same dimension as the one provided by `\texdimenbothcmin` and +> `\texdimenbothincm`. + +`\texdimenbothincmpt{<dim. expr.>}` (new with `0.9dev`) + +> Same as `\texdimenbothcminpt`. + +`\texdimenbothcminsp{<dim. expr.>}` (new with `0.9dev`) + +> Produces an integer (explicit digit tokens) `N` such that `Nsp` +> is the largest dimension smaller than the original one and +> exactly representable both in the `in` and `cm` units. + +`\texdimenbothincmsp{<dim. expr.>}` (new with `0.9dev`) + +> Same as `\texdimenbothcminsp`. + + ## Extras? As already stated the "up" and also the "down" macros for the `dd`, `nc` @@ -418,46 +454,28 @@ some demand for it. But of course anyhow the output from the "up" macros if used as input with the corresponding unit will be beyond `\maxdimen` if the -latter is not atteignable, i.e. for all units except `bp`, and `nd` +latter is not attainable, i.e. for all units except `bp`, and `nd` (and `pt` but there is no "up" macro for it). -Provide a macro `\texdimforbothincm{<dim.expr.>}` which would output -the nearest dimension simultaneously representable both in `in` and in -`cm`? - According to a reference on the web by an anonymous contributor the dimensions representable with both `in` and `cm` units have the shape -`trunc(3613.5*k) sp` for some integer `k`. So we basically may have a -delta up to about `1800sp` which is about `0.0275pt` and is still small -(less than one hundredth of a millimeter, i.e. less than ten micron), -so perhaps such a utility for -"safe dimensions" may be useful. Here are for example the dimensions -nearest to `1in` and realizable both in `in` and `cm` units: - - >>> \input texdimens.tex\relax - (executing \input texdimens.tex\relax in background) - (./texdimens.tex) - >>> &exact - exact mode (floating point evaluations use 16 digits) - >>> (\texdiminin{4737298sp}); - @_10 1.00021 - >>> (\texdimincm{4737298sp}); - @_11 2.54054 - >>> (\dimexpr1.00021in, \dimexpr2.54054cm); - @_12 4737298, 4737298 - >>> (\texdiminin{4733685sp}); - @_13 0.99945 - >>> (\texdimincm{4733685sp}); - @_14 2.5386 - >>> (\dimexpr0.99945in, \dimexpr2.5386cm); - @_15 4733685, 4733685 - -As promised, one of them, the upper approximation, is at less than -one hundredth of millimeter from the two nearby targets. - -Simpler however and more efficient -would be for people to finally adopt the French revolution Système -Métrique (rather than setting up giant financial paradises). +`trunc(3613.5*k)sp` for some integer `k`. The largest one smaller +than a given dimension will thus differ from it by at most about `0.055pt`, +which is also about `0.02mm`. + +For example `\texdimenbothincm{1cm}` expands to `0.99994cm` which maps +internally to `1864566sp` which differs from TeX's `1cm` by only +`-113sp`. It can be obtained from `0.39368in` or `28.45102pt`. + +And `\texdimenbothcmin{1in}` expands to `0.99945in`, maps internally to +`4733685sp` which differs from TeX's `1in` by `-2601sp`. It can be obtained +as `2.5386cm` or `72.2303pt`. + +Currently the package does not provide analogous approximations from above. +For the `1in` for example it would be `4737298sp`, i.e. `1.00021in` which +differs from TeX's `1in` by `+1012sp` and is obtained also as `2.54054cm` +and `72.28543pt`. + <!-- --> diff --git a/macros/generic/texdimens/texdimens.sty b/macros/generic/texdimens/texdimens.sty index dbf39c72f8..8467e69a6f 100644 --- a/macros/generic/texdimens/texdimens.sty +++ b/macros/generic/texdimens/texdimens.sty @@ -1,5 +1,5 @@ % This is file texdimens.tex, part of texdimens package, which % is distributed under the LPPL 1.3c. Copyright (c) 2021 Jean-François Burnol -\ProvidesPackage{texdimens}[2021/07/15 v0.9delta conversion of TeX dimensions to decimals (JFB)] +\ProvidesPackage{texdimens}[2021/07/21 v0.9 conversion of TeX dimensions to decimals (JFB)] \@@input texdimens.tex\relax \endinput
\ No newline at end of file diff --git a/macros/generic/texdimens/texdimens.tex b/macros/generic/texdimens/texdimens.tex index 189caca95d..8103bef1cd 100644 --- a/macros/generic/texdimens/texdimens.tex +++ b/macros/generic/texdimens/texdimens.tex @@ -1,29 +1,70 @@ % This is file texdimens.tex, part of texdimens package, which % is distributed under the LPPL 1.3c. Copyright (c) 2021 Jean-François Burnol -% 2021/07/15 v0.9delta +% 2021/07/21 v0.9 +% All macros from 0.9delta release have changed names: \texdimen prefix +% has replaced \texdimin. \edef\texdimensendinput{\endlinechar\the\endlinechar\catcode`\noexpand _=\the\catcode`\_\relax\noexpand\endinput}% \endlinechar13\relax% \catcode`\_=11 % -% Mathematics +% Mathematics ("down" and "up" macros) % =========== % -% Is T sp attainable from unit "uu"?. Here we suppose T>0. -% phi>1, psi=1/phi, psi<1 -% U(N,phi)=trunc(N phi) is strictly increasing +% Is T sp attainable from unit "uu"?. +% If not, what is largest dimension < Tsp which is attainable? +% Here we suppose T>0. +% +% phi>1, psi=1/phi, psi<1. +% +% U(N,phi)=trunc(N phi) is the strictly increasing sequence, +% indexed by non-negative integers, of attainable dimensions. +% (in sp unit) +% % U(N)<= T < U(N+1) iff N = ceil((T+1)psi) - 1 % U(M)< T <= U(M+1) iff M = ceil(T psi) - 1 -% Either: +% +% Stumbling block +% --------------- +% +% The stumbling block is that computing "ceil((T+1)psi) - 1" without +% overflow is not obvious: yes \numexpr/\dimexpr allow so-called +% "scaling operations" but only in the "rounding up" variant. +% +% If we attempt computing the ceil(x) function via round(x+0.5), +% for example with psi=100/7227 which corresponds to the unit "in", +% this necessitates evaluating: +% +% round((((T+1)*200)+7227)/14454) +% +% But as far as I can tell currently, for this we need to be able +% to evaluate without overflow (T+1)*200+7227 and this limits to +% T's which are (roughly) such that 100 T is less than \maxdimen. +% +% A work-around +% ------------- +% +% The rest of the discussion is about an algorithm providing an +% alternative route to N, using \numexpr/\dimexpr/TeX facilities, +% and working with (almost, as we will see) the full range of allowed +% T's, 0 < T <= \maxdimen. (that the algorithm works for T=0 is to be +% checked manually after the main discussion). +% +% Let's return to the U(N)<= T < U(N+1) and U(M)< T <= U(M+1) equations. +% +% Either (recall in all of this T > 0): +% % case1: M = N, i.e. T is not attainable, M=N < T psi < (T+1) psi <= N+1 -% case2: M = N - 1, i.e. T is attained, T psi <= N < (T+1) psi, T = floor(N phi) +% case2: M = N - 1, i.e. T is attained, T psi <= N < (T+1) psi, T = trunc(N phi) % -% Let X = round(T psi). And let Y = trunc(X phi). +% Let X = round(T psi). And let Y = trunc(X phi). We will explain later +% how X and Y can be computed using \numexpr/\dimexpr/TeX. % % case1: X can be N or N+1. It will be N+1 iff Y > T. % case2: X can be N or N-1. It will be N iff trunc((X+1)phi)>T. % -% This is not convenient: if Y <= T it might still be that we are in case 2 -% and we must check then if trunc((X+1) phi) > T or not. +% This is not convenient: if Y < T it could be that we are in case 2 +% but to decide we must check if trunc((X+1) phi) = T or not, so +% this means a second computation. % % If psi < 0.5 % ------------ @@ -37,11 +78,11 @@ % a) compute X = round(T psi) % b) compute Y = trunc(X phi) and test if Y > T. If true, we % were in case 1, replace X by X - 1, else we were either -% in case 1 or case 2, but we can leave X as is. +% in case 1 or case 2, and we leave X as it is. % We have thus found N. % % The operation Y = trunc(X phi) can be achieved this way: -% i) use \the\dimexpr to convert X sp into D pt, +% i) use \the\dimexpr to convert X sp into D pt, % ii) use \the\numexpr\dimexpr to convert "D uu" into sp. % These steps give Y. % @@ -50,14 +91,14 @@ % % The computations of X and Y can be done independently of sign of T. % But the final test has to be changed to Y < T if T < 0 and then -% one must replace X by X+1. So we must filter sign. +% one must replace X by X+1. So we must filter out the sign of the input. % -% If the goal is only to find a decimal D such that "D uu" is +% If the goal is only to find a decimal D such that "D uu" is % exactly T sp in the case this is possible, then things are simpler % because from X = round(T psi) we get D such as X sp is same as D pt % and "D uu" will work. % We don't have to take sign into account for this computation. -% But if T sp was not atteignable we don't know if this X will give +% But if T sp was not attainable we don't know if this X will give % a D such that D uu < T sp or D uu > T sp. % % If psi > 0.5 @@ -65,7 +106,7 @@ % % For example unit "bp" has phi=803/800. % -% It is then not true that if T sp is atteignable, the X = round(T psi) +% It is then not true that if T sp is attainable, the X = round(T psi) % will always work. % % But it is true that R = round((T + 0.5) psi) will always work. @@ -76,7 +117,7 @@ % % So this gives an approach to find a D such that "D uu" is exactly % T sp when this is possible. -% +% % If Tsp (positive) is not attainable, this R however can produce % either N or N+1. % @@ -86,42 +127,38 @@ % It is slightly less costly to compute X = round(T psi) than % R = round((T + 0.5) psi), % but if we then realize that trunc(X phi) < T we do not yet know -% if trunc((X+1) phi) = T or is > T. +% if trunc((X+1) phi) = T or is > T. So we proceed via R, not X, +% to not have to make a second computation if a dimension comparison +% test goes awry. % % To recapitulate: we have our algorithm for all units to find out -% maximal dimension exactly atteignable in "uu" unit and at most equal +% maximal dimension exactly attainable in "uu" unit and at most equal % to (positive) T sp. % % Unfortunately the check that Y (in case psi < 0.5) or Z (in case psi > -% 0.5) may trigger a Dimension too large error if T sp was near -% non-atteignable \maxdimen. -% -% For additional envisioned "safe versions" we would tabulate first per unit -% what is the integer Rmax such that trunc(Rmax phi) <= \maxdimen. Then -% the "safe" versions would have an extra check of X or R before -% proceeding further. But the "up macros" supposed to give the next -% dimension above Tsp and exactly atteignable in "uu" unit, if compliant -% to their description can not avoid "Dimension too large" for inputs -% close to non-attainable \maxdimen. -% -% After having written the macros we will tabulate what is for each unit -% the maximal attainable dimension. -% -% About the macros such as \texdiminbp whose constraints are: -% - give a decimal D such that "Duu" = "T sp" for TeX if possible -% - else give nearest from below or above without knowing -% which one, -% -% there was some hesitation about whether or not using the simpler -% round(T psi) approach for units > 2pt and the \texdimin<uu> macros. -% Testing showed that this did not change the output for \maxdimen -% with the units "nc" and "in": still N+1 is returned... -% -% As it has great -% advantage to not have to check the sign of the input, the -% "simpler" approach was chosen for those units to which it -% applies, i.e. the units uu > 2pt (phi>2, psi<1/2), i.e. -% all units except bp, nd and dd. +% 0.5) verifies or not Y > T may trigger a Dimension too large error if +% T sp was near non-attainable \maxdimen. It turns out this sad +% situation happens only for the units `dd`, `nc`, and `in`, and T sp +% very close to \maxdimen (like for all units apart from `pt`, `bp`, +% `nd`, the \maxdimen is not attainable, and by bad luck for `dd`, `nc`, +% and `in`, the X will correspond to a decimal D such that Duu>\maxdimen +% is the nearest virtually attaible dimensions from above not from +% below; see the README.md for the tabulation of the maximal usable inputs). +% +% Regarding the \texdimen<uu> macros, and units with phi > 2, I +% hesitated using either the round((T+0.5)psi) or round(T psi), but for +% Tsp = \maxdimen, both formulas turned out to give the same result for +% all such units, so I chose for these \texdimen<uu> macros and the +% units with phi>2 to use the simpler round(T psi) which does not need +% to check the sign of T. +% +% For the "up" and "down" macros, we again use the round(T psi), but do +% have to check the sign anyhow. We could also have used the +% round((T+0.5)psi) which requires a sign check too, but it costs a bit +% more. It would have allowed though to share the same codebase for all +% units, here we have to prepare some slightly different shared macros +% for the first batch bp, nd, dd and the second batch mm, pc, nc, cc, +% cm, in. % % Implementation % ============== @@ -171,87 +208,164 @@ % % pt % -\def\texdiminpt#1{\expandafter\texdimenstrippt\the\dimexpr#1\relax}% +\def\texdimenpt#1{\expandafter\texdimenstrippt\the\dimexpr#1\relax}% % % bp 7227/7200 = 803/800 % -\def\texdiminbp#1{\expandafter\texdiminbp_\the\numexpr\dimexpr#1;}% -\def\texdiminbp_#1#2;{% +\def\texdimenbp#1{\expandafter\texdimenbp_\the\numexpr\dimexpr#1;}% +\def\texdimenbp_#1#2;{% \expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if-#1-\fi1)*400/803sp\relax }% -% \texdiminbpdown: maximal dim exactly expressible in bp and at most equal to input -\def\texdiminbpdown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*400/803;bp;}% -% \texdiminbpup: minimal dim exactly expressible in bp and at least equal to input -\def\texdiminbpup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*400/803;bp;}% +% \texdimenbpdown: maximal dim exactly expressible in bp and at most equal to input +\def\texdimenbpdown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*400/803;bp;}% +% \texdimenbpup: minimal dim exactly expressible in bp and at least equal to input +\def\texdimenbpup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*400/803;bp;}% % % nd 685/642 % -\def\texdiminnd#1{\expandafter\texdiminnd_\the\numexpr\dimexpr#1;}% -\def\texdiminnd_#1#2;{% +\def\texdimennd#1{\expandafter\texdimennd_\the\numexpr\dimexpr#1;}% +\def\texdimennd_#1#2;{% \expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if-#1-\fi1)*321/685sp\relax }% -% \texdiminnddown: maximal dim exactly expressible in nd and at most equal to input -\def\texdiminnddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*321/685;nd;}% -% \texdiminndup: minimal dim exactly expressible in nd and at least equal to input -\def\texdiminndup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*321/685;nd;}% +% \texdimennddown: maximal dim exactly expressible in nd and at most equal to input +\def\texdimennddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*321/685;nd;}% +% \texdimenndup: minimal dim exactly expressible in nd and at least equal to input +\def\texdimenndup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*321/685;nd;}% % % dd 1238/1157 % -\def\texdimindd#1{\expandafter\texdimindd_\the\numexpr\dimexpr#1;}% -\def\texdimindd_#1#2;{% +\def\texdimendd#1{\expandafter\texdimendd_\the\numexpr\dimexpr#1;}% +\def\texdimendd_#1#2;{% \expandafter\texdimenstrippt\the\dimexpr\numexpr(2*#1#2+\if-#1-\fi1)*1157/2476sp\relax }% -% \texdimindddown: maximal dim exactly expressible in dd and at most equal to input -\def\texdimindddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*1157/2476;dd;}% -% \texdiminddup: minimal dim exactly expressible in dd and at least equal to input -\def\texdiminddup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*1157/2476;dd;}% +% \texdimendddown: maximal dim exactly expressible in dd and at most equal to input +\def\texdimendddown#1{\expandafter\texdimendown_A\the\numexpr\dimexpr#1;*1157/2476;dd;}% +% \texdimenddup: minimal dim exactly expressible in dd and at least equal to input +\def\texdimenddup#1{\expandafter\texdimenup_A\the\numexpr\dimexpr#1;*1157/2476;dd;}% % % mm 7227/2540 phi now >2, use from here on the simpler approach % -\def\texdiminmm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*2540/7227\relax}% -% \texdiminmmdown: maximal dim exactly expressible in mm and at most equal to input -\def\texdiminmmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*2540/7227;mm;}% -% \texdiminmmup: minimal dim exactly expressible in mm and at least equal to input -\def\texdiminmmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*2540/7227;mm;}% +\def\texdimenmm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*2540/7227\relax}% +% \texdimenmmdown: maximal dim exactly expressible in mm and at most equal to input +\def\texdimenmmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*2540/7227;mm;}% +% \texdimenmmup: minimal dim exactly expressible in mm and at least equal to input +\def\texdimenmmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*2540/7227;mm;}% % % pc 12/1 % -\def\texdiminpc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)/12\relax}% -% \texdiminpcdown: maximal dim exactly expressible in pc and at most equal to input -\def\texdiminpcdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;/12;pc;}% -% \texdiminpcup: minimal dim exactly expressible in pc and at least equal to input -\def\texdiminpcup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;/12;pc;}% +\def\texdimenpc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)/12\relax}% +% \texdimenpcdown: maximal dim exactly expressible in pc and at most equal to input +\def\texdimenpcdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;/12;pc;}% +% \texdimenpcup: minimal dim exactly expressible in pc and at least equal to input +\def\texdimenpcup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;/12;pc;}% % % nc 1370/107 % -\def\texdiminnc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*107/1370\relax}% -% \texdiminncdown: maximal dim exactly expressible in nc and at most equal to input -\def\texdiminncdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*107/1370;nc;}% -% \texdiminncup: minimal dim exactly expressible in nc and at least equal to input -\def\texdiminncup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*107/1370;nc;}% +\def\texdimennc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*107/1370\relax}% +% \texdimenncdown: maximal dim exactly expressible in nc and at most equal to input +\def\texdimenncdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*107/1370;nc;}% +% \texdimenncup: minimal dim exactly expressible in nc and at least equal to input +\def\texdimenncup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*107/1370;nc;}% % % cc 14856/1157 % -\def\texdimincc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*1157/14856\relax}% -% \texdiminccdown: maximal dim exactly expressible in cc and at most equal to input -\def\texdiminccdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*1157/14856;cc;}% -% \texdiminccup: minimal dim exactly expressible in cc and at least equal to input -\def\texdiminccup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*1157/14856;cc;}% +\def\texdimencc#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*1157/14856\relax}% +% \texdimenccdown: maximal dim exactly expressible in cc and at most equal to input +\def\texdimenccdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*1157/14856;cc;}% +% \texdimenccup: minimal dim exactly expressible in cc and at least equal to input +\def\texdimenccup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*1157/14856;cc;}% % % cm 7227/254 % -\def\texdimincm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*254/7227\relax}% -% \texdimincmdown: maximal dim exactly expressible in cm and at most equal to input -\def\texdimincmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*254/7227;cm;}% -% \texdimincmup: minimal dim exactly expressible in cm and at least equal to input -\def\texdimincmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*254/7227;cm;}% +\def\texdimencm#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*254/7227\relax}% +% \texdimencmdown: maximal dim exactly expressible in cm and at most equal to input +\def\texdimencmdown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*254/7227;cm;}% +% \texdimencmup: minimal dim exactly expressible in cm and at least equal to input +\def\texdimencmup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*254/7227;cm;}% % % in 7227/100 % -\def\texdiminin#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*100/7227\relax}% -% \texdiminindown: maximal dim exactly expressible in in and at most equal to input -\def\texdiminindown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*100/7227;in;}% -% \texdimininup: minimal dim exactly expressible in in and at least equal to input -\def\texdimininup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*100/7227;in;}% +\def\texdimenin#1{\expandafter\texdimenstrippt\the\dimexpr(#1)*100/7227\relax}% +% \texdimenindown: maximal dim exactly expressible in in and at most equal to input +\def\texdimenindown#1{\expandafter\texdimendown_a\the\numexpr\dimexpr#1;*100/7227;in;}% +% \texdimeninup: minimal dim exactly expressible in in and at least equal to input +\def\texdimeninup#1{\expandafter\texdimenup_a\the\numexpr\dimexpr#1;*100/7227;in;}% +% both in and cm +% Mathematics ("both" macros) +% =========== +% +% Let a and b be two non-negative integers such that U = floor(a 7227/100) = +% floor(b 7227/254). It can be proven that a=50k, b=127k for some integer k. +% The proof is left to reader. So U = floor(7227 k /2) for some k. +% +% Let's now find the largest such U <= T. So U = floor(k 7227/2)<= T which is +% equivalent (as k is integer) to k 7227/2 <= T + 1/2, i.e. +% +% kmax = floor((2T+1)/7227) +% +% If we used for x>0 the formula floor(x)=round(x-1/2)=<x-1/2> we would end +% up basically with some 4T hence overflow problems even in \numexpr. +% Here I used <.> to denote rounding in the sense of \numexpr. It is not +% 1-periodical due to how negative inputs are handled, but here x-1/2>-1/2. +% +% The following lemma holds: let T be a non-negative integer then +% +% floor((2T+1)/7227) = <(2T - 3612)/7227> +% +% So we can compute this k, hence get a=50k, b=127k, all within \numexpr and +% avoiding overflow. +% +% Implementation +% ============== % +% Regarding the output in pt or sp, we seem to need floor(k 7227/2). +% The computation of floor(k 7227/2) as <(7227 k - 1)/2> would require to +% check if k==0 so we do it rather as <(7227 k + 1)/2> - 1. No overflow +% can arise as k = 297147 for \maxdimen, and then 7227 k = 2**31 - 2279 and +% there is ample room for 7227k+1 using \numexpr. +% +% But this step, as well as initial step to get kmax will require to separate +% hangdling of negative input from positive one. +% +% Alternative +% ----------- +% +% For non-negative T we can compute U = ((T+1)/7227)*7227. If U <= T keep it, +% else if U > T, replace it by U - 3614. This is alternative road to the maximal +% floor(k 7227/2) at most equal to T. +% +% There is some slight under-efficiency to share macros across the 3 end targets +% as I added one layer of parentheses. +\def\texdimenbothincm#1{\expandafter\texdimenstrippt\the\dimexpr + \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;127);}% +\def\texdimenbothcmin#1{\expandafter\texdimenstrippt\the\dimexpr + \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;50);}% +\def\texdimenbothincmpt#1{\expandafter\texdimenstrippt\the\dimexpr + \expandafter\texdimenboth_a\the\numexpr\dimexpr#1;7227+1)/2-1;}% +\let\texdimenbothcminpt\texdimenbothincmpt +\def\texdimenboth_a#1{\if-#1\texdimenboth_neg\fi\texdimenboth_b#1}% +% The opening parenthesis ( is closed in #2, it was added to share "pt" output +% with the two others +\def\texdimenboth_b#1;#2;{\numexpr(((2*#1-3612)/7227)*#2sp\relax}% +% negative branch. This is expanded in a \dimexpr so we can insert the - +% in front of the \numexpr. +% #1 is \fi here and #2 is \texdimenboth_b +\def\texdimenboth_neg#1#2-#3;#4;{#1-\numexpr(((2*#3-3612)/7227)*#4sp\relax}% +% +% \texdimenbothincmsp is done separately as I found no easy way to share +% its macros with the others; alternative would have been to make it the +% core, and derive the others from it, (\texdimencm{\texdimenbothincmsp{...}sp}) +% but then they would be less efficient than their current versions. +% (it is a bit ironical to worry about not creating too many macros +% in such a small package, by the way) +\def\texdimenbothincmsp#1{\the\numexpr\expandafter\texdimenbothsp_a\the\numexpr\dimexpr#1;}% +\def\texdimenbothsp_a#1{\if-#1\texdimenbothsp_neg\fi\texdimenbothsp_b#1}% +\def\texdimenbothsp_b#1;{(((2*#1-3612)/7227)*7227+1)/2-1\relax}% +% #1 is \fi +% we need to regrab here or to add a \numexpr..\relax layer to +% \texdimenbothsp_b (parentheses could do but using 0-(...) syntax) +% finally doing the job of \texdimenbothsp_b directly +\def\texdimenbothsp_neg#1#2-#3;{#1-\numexpr(((2*#3-3612)/7227)*7227+1)/2-1\relax\relax}% +% +\let\texdimenbothcminsp\texdimenbothincmsp \texdimensendinput diff --git a/macros/generic/xstring/README b/macros/generic/xstring/README index 8234833cb9..ce2ea5d24e 100644 --- a/macros/generic/xstring/README +++ b/macros/generic/xstring/README @@ -1,8 +1,8 @@ _________________ xstring package - v 1.83 - 2019/02/06 + v 1.84 + 2021/07/21 _________________ This package provides macros manipulating strings for programming use. diff --git a/macros/generic/xstring/test_etex.pdf b/macros/generic/xstring/test_etex.pdf Binary files differindex 4d2b8134b2..17cb0ae3ac 100644 --- a/macros/generic/xstring/test_etex.pdf +++ b/macros/generic/xstring/test_etex.pdf diff --git a/macros/generic/xstring/test_latex.pdf b/macros/generic/xstring/test_latex.pdf Binary files differindex 2642a17751..8a1ee001e8 100644 --- a/macros/generic/xstring/test_latex.pdf +++ b/macros/generic/xstring/test_latex.pdf diff --git a/macros/generic/xstring/xstring-en.pdf b/macros/generic/xstring/xstring-en.pdf Binary files differindex d7581cd5e1..7a9da7b093 100644 --- a/macros/generic/xstring/xstring-en.pdf +++ b/macros/generic/xstring/xstring-en.pdf diff --git a/macros/generic/xstring/xstring-en.tex b/macros/generic/xstring/xstring-en.tex index 94c46f9d3f..61b6ad8078 100644 --- a/macros/generic/xstring/xstring-en.tex +++ b/macros/generic/xstring/xstring-en.tex @@ -178,7 +178,7 @@ In the following chapters, all the macros will be presented this plan: \textbf{Important}: in the following, a \argu{number} can be an integer written with numeric chars, a counter, or the result of an arithmetic operation made with the command \verbinline|\numexpr|.\smallskip -All the macros of \Xstring are displayed in {\makeatletter\color{@xs@keywordsxstring}red}. +All the macros of \Xstring are displayed in {\makeatletter\color{@xs@keywordsxstring}blue}. \subsection{The tests} \subsubsection{\ttfamily\textbackslash IfSubStr} diff --git a/macros/generic/xstring/xstring-fr.pdf b/macros/generic/xstring/xstring-fr.pdf Binary files differindex a1f72f8635..0550b0393d 100644 --- a/macros/generic/xstring/xstring-fr.pdf +++ b/macros/generic/xstring/xstring-fr.pdf diff --git a/macros/generic/xstring/xstring-fr.tex b/macros/generic/xstring/xstring-fr.tex index a339416149..0949306ec0 100644 --- a/macros/generic/xstring/xstring-fr.tex +++ b/macros/generic/xstring/xstring-fr.tex @@ -182,7 +182,7 @@ Dans ce chapitre, la totalité des macros est présentée selon ce plan :\par\no \textbf{Important} : dans les macros qui suivent, sauf cas spécifié, un \argu{nombre} est un nombre entier, un compteur, ou le résultat d'une opération arithmétique effectuée à l'aide de la primitive \verb|\numexpr|.\smallskip -Dans le reste du texte, les macros de \Xstring sont affichées en {\makeatletter\color{@xs@keywordsxstring}rouge}. +Dans le reste du texte, les macros de \Xstring sont affichées en {\makeatletter\color{@xs@keywordsxstring}bleu}. \subsection{Les tests} \subsubsection{\ttfamily\textbackslash IfSubStr} diff --git a/macros/generic/xstring/xstring.tex b/macros/generic/xstring/xstring.tex index 654fe462ae..d5dcd6354f 100644 --- a/macros/generic/xstring/xstring.tex +++ b/macros/generic/xstring/xstring.tex @@ -1,12 +1,12 @@ -% !TeX encoding = ISO-8859-1 +% !TeX encoding = UTF-8 % Ce fichier contient le code de l'extension "xstring" % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % \def\xstringname {xstring} % -\def\xstringversion {1.83} % +\def\xstringversion {1.84} % % % -\def\xstringdate {2019/02/06} % +\def\xstringdate {2021/07/21} % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % @@ -32,7 +32,7 @@ \immediate\write-1 {Package: xstring \xstringdate\space v\xstringversion\space String manipulations (CT)}% \fi \newcount\integerpart -\newcount\decimalpart% compteurs utilisés par xstring +\newcount\decimalpart% compteurs utilisés par xstring \edef\restorexstringcatcode{\catcode\number`\_ =\number\catcode`\_\relax} \catcode`\_=11 @@ -76,14 +76,14 @@ \xs_read_verb } -\def\setverbdelim#1{% définit quel est le délimiteur de verb +\def\setverbdelim#1{% définit quel est le délimiteur de verb \xs_exparg\xs_ifempty{\xs_gobarg#1}% {} {\errmessage{Package xstring Warning: verb delimiter "\detokenize{#1}" is not a single token}}% - \def\xs_read_verb##1#1##2#1{\endgroup\xs_assign_verb{##2}}% on appelle l'exécution de fin + \def\xs_read_verb##1#1##2#1{\endgroup\xs_assign_verb{##2}}% on appelle l'exécution de fin } -% Assigne l'argument entre délimiteur verb dans la sc #1 +% Assigne l'argument entre délimiteur verb dans la sc #1 \def\verbtocs#1{% \def\xs_assign_verb##1{\def#1{##1}}% \xs_toks_toverb @@ -99,7 +99,7 @@ \def\tokenize#1#2{% \begingroup - \xs_def\xs_reserved_A{#2}% on développe en accord avec \fullexpandarg ou \noexpandarg + \xs_def\xs_reserved_A{#2}% on développe en accord avec \fullexpandarg ou \noexpandarg \everyeof\expandafter{\xs_twozeroschars#1}% \endlinechar-1 \expandafter\xs_assigntokenizeresult\scantokens\expandafter{\expandafter\relax\xs_reserved_A}% on fait l'assignation @@ -111,18 +111,18 @@ \def\xs_ledef{\long\edef} \def\normalexpandarg{% - \let\xs_def\xs_ldef% on définit \xs_call avec \def + \let\xs_def\xs_ldef% on définit \xs_call avec \def \def\xs_expand##1{\unexpanded\expandafter{##1}}% } \let\noexpandarg\normalexpandarg% synonyme \def\expandarg{% - \let\xs_def\xs_ldef% on définit \xs_call avec \def + \let\xs_def\xs_ldef% on définit \xs_call avec \def \def\xs_expand##1{\unexpanded\expandafter\expandafter\expandafter{##1}}% } \def\fullexpandarg{% - \let\xs_def\xs_ledef% on définit\xs_call avec \edef + \let\xs_def\xs_ledef% on définit\xs_call avec \edef \def\xs_expand##1{##1}% et on neutralise \xs_expand } @@ -144,7 +144,7 @@ \endcsname } -% Cette macro interne prend la 1ere unité syntaxique de #1 et assigne le résultat à #2 +% Cette macro interne prend la 1ere unité syntaxique de #1 et assigne le résultat à #2 \long\def\xs_returnfirstsyntaxunit#1#2{% \let\xs_toks\relax \xs_ifempty{#1} @@ -179,18 +179,18 @@ }% } -% Cette macro interne est utilisée dans les macros étoilées pour : -% 1) développer l'argument selon qu'on a choisit \fullexpandarg -% ou \normalexpandarg, et ceci à l'aide de la macro \xs_def -% 2) Ensuite, on détokenize ce développement de façon n'avoir plus que +% Cette macro interne est utilisée dans les macros étoilées pour : +% 1) développer l'argument selon qu'on a choisit \fullexpandarg +% ou \normalexpandarg, et ceci à l'aide de la macro \xs_def +% 2) Ensuite, on détokenize ce développement de façon n'avoir plus que % des catcodes de 10 pour les espaces et 12 pour le reste. \long\def\xs_expand_and_detokenize#1#2{% \long\def#1{#2}% - \expandafter\edef\expandafter#1\expandafter{\xs_expand#1}% on développe #2 selon le mode de développement - \long\edef#1{\detokenize\expandafter{#1}}% puis on détokenize et on assigne à #1 + \expandafter\edef\expandafter#1\expandafter{\xs_expand#1}% on développe #2 selon le mode de développement + \long\edef#1{\detokenize\expandafter{#1}}% puis on détokenize et on assigne à #1 } -\long\def\xs_expand_and_assign#1#2{\xs_def#1{#2}}% on développe #2 selon \fullexpandarg ou \normalexpandarg +\long\def\xs_expand_and_assign#1#2{\xs_def#1{#2}}% on développe #2 selon \fullexpandarg ou \normalexpandarg \def\xs_arglist{0########1########2########3########4########5########6########7########8########9} @@ -205,7 +205,7 @@ \def\xs_assign_one_arg#1{\xs_exparg\xs_assign_one_arg_i{\number\numexpr#1-1}{#1}} \def\xs_assign_one_arg_i#1#2{\def\xs_assign_one_arg_ii##1#1##2#2##3\_nil{\def\xs_myarg{##2#2}}\expandafter\xs_assign_one_arg_ii\xs_arglist\_nil} -% #1 : numéro du 1er argument; #2 : nombre de lignes; #3 argument optionnel; #4 : dernier numéro de l'argument devant être détokenisé si étoile +% #1 : numéro du 1er argument; #2 : nombre de lignes; #3 argument optionnel; #4 : dernier numéro de l'argument devant être détokenisé si étoile \def\xs_buildlines#1#2#3#4{% \let\xs_newlines\empty \let\xs_newargs\empty @@ -218,7 +218,7 @@ \edef\xs_reserved_B{\ifnum##1>#4 xs_def\else xs_assign\fi}% }% et s'il y a un argument optionnel alors, on met des crochets {\xs_eaddtomacro\xs_newargs{\expandafter[\xs_reserved_B]}% - \def\xs_reserved_B{xs_def}% ne pas détokéniser l'argument optionnel grace au \xs_def + \def\xs_reserved_B{xs_def}% ne pas détokéniser l'argument optionnel grace au \xs_def }% } {\xs_eaddtomacro\xs_newargs{\expandafter{\xs_reserved_B}}% @@ -238,7 +238,7 @@ {\let\xs_reserved_D\relax\xs_newmacro_0}% } -% #1 : dernier numéro de l'argument devant être détokenisé +% #1 : dernier numéro de l'argument devant être détokenisé % #2 : nom de la macro publique % #3 : argument optionnel (vide si pas d'arg optionnel) % #4 : nombre d'arguments obligatoires @@ -263,7 +263,7 @@ \noexpand\xs_testopt{\expandafter\noexpand\csname\xs_reserved_A __\endcsname}{\ifx\xs_def\xs_ledef#3\else\unexpanded{#3}\fi}}% \fi }% - % Que fait \xs_reserved_B ? Il définit : + % Que fait \xs_reserved_B ? Il définit : % si #3 est vide : \NOM{\xs_ifstar{\let\xs_assign\xs_expand_and_detokenize\xs_NOM__}{\let\xs_assign\xs_expand_and_assign\xs_NOM__}} % si #3 existe : \NOM{\xs_ifstar{\let\xs_assign\xs_expand_and_detokenize\xs_NOM_}{\let\xs_assign\xs_expand_and_assign\xs_NOM_}} % \xs_NOM_{\xs_testopt{\xs_NOM__}{#3}}} @@ -281,7 +281,7 @@ \ifnum#5=1 \edef\xs_reserved_D{\noexpand\noexpand\noexpand\xs_testopt{\unexpanded\expandafter{\xs_reserved_D}}{}}\fi \xs_edefaddtomacro\xs_reserved_C{{\unexpanded\expandafter{\xs_reserved_D}}\noexpand\xs_call}% \xs_edefaddtomacro\xs_reserved_B{{\unexpanded\expandafter{\xs_reserved_C}}}% - % Que fait \xs_reserved_B ? Il définit par exemple pour 3 arguments obligatoires et 1 facultatif : + % Que fait \xs_reserved_B ? Il définit par exemple pour 3 arguments obligatoires et 1 facultatif : % \def\xs_NOM__[##2]##3##4##5{% % \xs_def\xs_arg_i{##2}\xs_assign\xs_arg_ii{##3}\xs_assign\xs_arg_iii{##4}\xs_asign\xs_arg_iv{##5}% % si #5=0: \edef\xs_call{\noexpand\xs_NOM[\xs_expand\xs_arg_i]{\xs_expand\xs_arg_ii}{\xs_expand\xs_arg_iii}{\xs_expand\xs_arg_iv}}% @@ -292,15 +292,15 @@ \def\expandafter\noexpand\csname\xs_reserved_A\endcsname \xs_myarg\ifnum#5=1 [\unexpanded{##}\number\numexpr\ifx\empty#3\empty#4+1\else#4+2\fi]\fi }% - % Que fait \xs_reserved_B ? Il définit par exemple pour 3 arguments obligatoires et 1 facultatif : + % Que fait \xs_reserved_B ? Il définit par exemple pour 3 arguments obligatoires et 1 facultatif : % \def \xs_NOM[##2]##3##4##5[##6]{#6} \long\xs_reserved_B } -% macro générique qui lit \xs_reserved_C us par us -% 3 sous-routines sont appelées à des moments clé : -% \xs_atendofgroup (un groupe se finit, appel récursif) -% \xs_atbegingroup (un groupe vient d'être ouvert) +% macro générique qui lit \xs_reserved_C us par us +% 3 sous-routines sont appelées à des moments clé : +% \xs_atendofgroup (un groupe se finit, appel récursif) +% \xs_atbegingroup (un groupe vient d'être ouvert) % \xs_atnextsyntaxunit (la future US n'est pas un groupe) \def\xs_read_reserved_C{% \xs_exparg\xs_ifempty{\xs_reserved_C}% @@ -329,9 +329,9 @@ }% } -% macro générique qui lit \xs_reserved_D en procédant à des tests avec \IfBeginWith -% 1 sous-routine est appelée : -% \xs_atoccurfound (une occurrence a été trouvée) +% macro générique qui lit \xs_reserved_D en procédant à des tests avec \IfBeginWith +% 1 sous-routine est appelée : +% \xs_atoccurfound (une occurrence a été trouvée) \def\xs_read_reserved_D{% \xs_exparg\xs_ifempty{\xs_reserved_D}% {\xs_ifnum{\xs_nestlevel=0 } @@ -403,11 +403,11 @@ }% } -% \xs_cutafteroccur coupe l'argument #1 après la #3ème occurrence de #2 +% \xs_cutafteroccur coupe l'argument #1 après la #3ème occurrence de #2 % \xs_reserved_C : contient ce qui se trouve avant cette occurrence % \xs_reserved_D : contient ce qui se trouve avant cette occurrence y compris cette occurrence -% \xs_reserved_E : contient ce qui se trouve après l'occurrence -% si l'occurrence n'existe pas ou qu'un des arguments est vide, toutes les chaines renvoyées sont vides +% \xs_reserved_E : contient ce qui se trouve après l'occurrence +% si l'occurrence n'existe pas ou qu'un des arguments est vide, toutes les chaines renvoyées sont vides \long\def\xs_cutafteroccur#1#2#3{% \xs_ifnum{#3<1 } {\let\xs_reserved_C\empty\let\xs_reserved_E\empty\gdef\groupID{}} @@ -425,13 +425,13 @@ \noexpand\decimalpart=\number\decimalpart\relax }% \expandafter\xs_exitallgroups\__temp - \xs_gobarg% mange l'appel récursif \xs_read_reserved_D dans \xs_read_reserved_D + \xs_gobarg% mange l'appel récursif \xs_read_reserved_D dans \xs_read_reserved_D } {\xs_eaddtomacro\xs_reserved_C{\xs_reserved_E}% }% }% \xs_read_reserved_D - \xs_ifnum{\decimalpart=\numexpr(#3)\relax}% occurrence trouvée ? + \xs_ifnum{\decimalpart=\numexpr(#3)\relax}% occurrence trouvée ? {\let\xs_reserved_E\xs_reserved_D \xs_exparg{\def\xs_reserved_D}{\xs_reserved_C#2}% } @@ -454,16 +454,16 @@ \long\def\xs_IfBeginWith_i#1#2{% \xs_ifempty{#2}% - {\xs_execfirst% #2 est vide, tous les tests sont passés avec succès : on renvoie #3 + {\xs_execfirst% #2 est vide, tous les tests sont passés avec succès : on renvoie #3 } {\xs_ifempty{#1}% {\xs_execsecond% #1 est vide, c'est que #2 est + long que #1 : on renvoie #4 } {\xs_returnfirstsyntaxunit{#2}\xs_reserved_B \xs_returnfirstsyntaxunit{#1}\xs_reserved_A - \xs_ifx{\xs_reserved_A\xs_reserved_B}% il y a égalité... + \xs_ifx{\xs_reserved_A\xs_reserved_B}% il y a égalité... {\xs_removefirstsyntaxunit{#2}\xs_reserved_B - \xs_removefirstsyntaxunit{#1}\xs_reserved_A% on enlève les 1ere unités syntaxiques + \xs_removefirstsyntaxunit{#1}\xs_reserved_A% on enlève les 1ere unités syntaxiques \xs_exptwoargs\xs_IfBeginWith_i\xs_reserved_A\xs_reserved_B } {\xs_execsecond @@ -538,7 +538,7 @@ \expandafter\xs_testdot\afterinteger\_nil \xs_ifx{\empty\afterdecimal} {\xs_ifnum{\decimalpart=0 } - {\xs_execfirst% partie décimale constituée de 0 --> seul cas où on renvoie vrai + {\xs_execfirst% partie décimale constituée de 0 --> seul cas où on renvoie vrai } {\expandafter\xs_defafterinteger\xs_after_intpart\relax\_nil \xs_execsecond @@ -583,36 +583,36 @@ \expandafter\xs_defafterdecimal\afterinteger\_nil } -% test d'égalité sur des chaines (et des chaines contenant des nombres) +% test d'égalité sur des chaines (et des chaines contenant des nombres) \long\def\xs_IfStrEqFalse_i#1#2{\let\xs_reserved_A\xs_execsecond} -\long\def\xs_IfStrEqFalse_ii#1#2{% renvoie vrai si les 2 arg sont décimaux et s'ils sont égaux, faux sinon +\long\def\xs_IfStrEqFalse_ii#1#2{% renvoie vrai si les 2 arg sont décimaux et s'ils sont égaux, faux sinon \xs_IfDecimal{#1}% {\xs_IfDecimal{#2}% {\ifdim#1pt=#2pt \let\xs_reserved_A\xs_execfirst \else \let\xs_reserved_A\xs_execsecond - \fi% les 2 sont décimaux : on fait le test + \fi% les 2 sont décimaux : on fait le test }% - {\let\xs_reserved_A\xs_execsecond}% un seul est décimal + {\let\xs_reserved_A\xs_execsecond}% un seul est décimal }% - {\let\xs_reserved_A\xs_execsecond}% #1 n'est pas décimal + {\let\xs_reserved_A\xs_execsecond}% #1 n'est pas décimal } -\long\def\xs_TestEqual#1#2{% teste si les 2 arguments sont égaux +\long\def\xs_TestEqual#1#2{% teste si les 2 arguments sont égaux \def\xs_reserved_A{#1}\def\xs_reserved_B{#2}% \xs_ifx{\xs_reserved_A\xs_reserved_B} - {\let\xs_reserved_A\xs_execfirst}% égalité parfaite des 2 chaines + {\let\xs_reserved_A\xs_execfirst}% égalité parfaite des 2 chaines {\xs_reserved_D{#1}{#2}}% \xs_reserved_A } -\xs_newmacro*2\IfStrEq{}{2}{0}{% teste si les deux chaines sont égales +\xs_newmacro*2\IfStrEq{}{2}{0}{% teste si les deux chaines sont égales \let\xs_reserved_D\xs_IfStrEqFalse_i \xs_TestEqual{#1}{#2}% } -\xs_newmacro*2\IfEq{}{2}{0}{% teste si les 2 arguments (chaine ou nombre) sont égaux +\xs_newmacro*2\IfEq{}{2}{0}{% teste si les 2 arguments (chaine ou nombre) sont égaux \let\xs_reserved_D\xs_IfStrEqFalse_ii \xs_TestEqual{#1}{#2}% } @@ -629,12 +629,12 @@ {\xs_IfStringCase\IfEq}% } -\long\def\xs_IfStringCase#1#2#3{% #1=macro avec ou sans étoile #2=argument à tester #3=liste des {<cas>}{code>} - \long\def\xs_testcase##1##2##3\_nil{% lit les 2 premieres unités syntaxiques dans ##1 et ##2. Les autres dans ##3 +\long\def\xs_IfStringCase#1#2#3{% #1=macro avec ou sans étoile #2=argument à tester #3=liste des {<cas>}{code>} + \long\def\xs_testcase##1##2##3\_nil{% lit les 2 premieres unités syntaxiques dans ##1 et ##2. Les autres dans ##3 #1{#2}{##1}% compare - {\xs_testopt{\xs_IfStringCase_ii{##2}}{}}% le test est positif, on exécute le code correspondant et on mange l'argument optionnel ## BUGfix dans 1.82 + {\xs_testopt{\xs_IfStringCase_ii{##2}}{}}% le test est positif, on exécute le code correspondant et on mange l'argument optionnel ## BUGfix dans 1.82 {\xs_ifempty{##3}% - {\xs_testopt{\xs_IfStringCase_i}{}}% s'il n'y a plus de cas, on exécute le code <autres cas> ## BUGfix dans 1.82 + {\xs_testopt{\xs_IfStringCase_i}{}}% s'il n'y a plus de cas, on exécute le code <autres cas> ## BUGfix dans 1.82 {\xs_testcase##3\_nil}% sinon, on recommence avec ce qui reste }% }% @@ -644,19 +644,19 @@ \long\def\xs_IfStringCase_i[#1]{#1} \long\def\xs_IfStringCase_ii#1[#2]{#1} -% Renvoie ce qui est à gauche de l'occurence n°#1 de la sous chaine #3 dans la chaine #2 +% Renvoie ce qui est à gauche de l'occurence n°#1 de la sous chaine #3 dans la chaine #2 \xs_newmacro*3\StrBefore{1}{2}{1}{% \xs_cutafteroccur{#2}{#3}{#1}% \xs_exparg\xs_assign_xstringresult{\xs_reserved_C}{#4}% } -% Renvoie ce qui est à droite de l'occurence n°#1 de la sous chaine #3 dans la chaine #2 +% Renvoie ce qui est à droite de l'occurence n°#1 de la sous chaine #3 dans la chaine #2 \xs_newmacro*3\StrBehind{1}{2}{1}{% \xs_cutafteroccur{#2}{#3}{#1}% \xs_exparg\xs_assign_xstringresult{\xs_reserved_E}{#4}% } -% Renvoie ce qui est strictement compris entre les occurrences n°#1 et n°#2 +% Renvoie ce qui est strictement compris entre les occurrences n°#1 et n°#2 % des chaines #4 et #5 dans la chaine #3 \xs_newmacro*4\StrBetween{1,1}{3}{1}{\xs_StrBetween_i[#1]{#2}{#3}{#4}[#5]} \long\def\xs_StrBetween_i[#1,#2]#3#4#5[#6]{% @@ -675,7 +675,7 @@ \def\saveexploremode{\let\xs_saveexploremode\xs_exploregroups} \def\restoreexploremode{\let\xs_exploregroups\xs_saveexploremode} -% Remplace les #1 premières occurences de la chaine #3 +% Remplace les #1 premières occurences de la chaine #3 % par la chaine #4 dans la chaine #2 \xs_newmacro\StrSubstitute{0}{3}{1}{% \def\xs_reserved_D{#2}\let\xs_reserved_C\empty\def\xs_reserved_E{#3}% @@ -697,12 +697,12 @@ }% } -% Supprime les #1 premières occurrences de #3 dans #2 +% Supprime les #1 premières occurrences de #3 dans #2 \xs_newmacro\StrDel{0}{2}{1}{\xs_StrSubstitute[#1]{#2}{#3}{}[#4]} \def\xs_exitallgroups{\ifnum\xs_nestlevel>0 \endgroup\expandafter\xs_exitallgroups\fi} -% Compte combien d'unités syntaxiques contient la chaine #1 ? +% Compte combien d'unités syntaxiques contient la chaine #1 ? \xs_newmacro\StrLen{}{1}{1}{% \def\xs_reserved_C{#1}\decimalpart0 \def\xs_nestlevel{0}\gdef\groupID{0}% \let\xs_atbegingroup\relax @@ -712,11 +712,11 @@ \xs_exparg\xs_assign_xstringresult{\number\decimalpart}{#2}% } -% Macro interne fermant autant de groupes que nécessaire pour trouver une unité syntaxique derrière +% Macro interne fermant autant de groupes que nécessaire pour trouver une unité syntaxique derrière \def\xs_continuetonext{% \xs_exparg\xs_ifempty{\xs_reserved_C}% {\ifnum\xs_nestlevel>0 - \xs_endgroup_eaddtomacro\xs_reserved_B{\expandafter{\xs_reserved_B}}% on concatène + \xs_endgroup_eaddtomacro\xs_reserved_B{\expandafter{\xs_reserved_B}}% on concatène \expandafter\xs_continuetonext% on recommence \fi} {}% @@ -729,7 +729,7 @@ {\endgroup\xs_eearg{\gdef\groupID}{\expandafter\groupID\expandafter,\number\integerpart}}% } -% Cette macro coupe la chaine #1 après l'unité syntaxique n°#2 +% Cette macro coupe la chaine #1 après l'unité syntaxique n°#2 \def\StrSplit{% \xs_ifstar {\let\xs_reserved_E\xs_continuetonext\StrSplit_i}% @@ -738,8 +738,8 @@ \xs_newmacro\StrSplit_i{}{2}{0}{\xs_StrSplit_ii{#2}{#1}\xs_StrSplit_iii} -% Cette macro interne coupe la chaine #2 après l'unité syntaxique n°#1 -% Le début est assigné dans \xs_reserved_B et la fin dans \xs_reserved_C +% Cette macro interne coupe la chaine #2 après l'unité syntaxique n°#1 +% Le début est assigné dans \xs_reserved_B et la fin dans \xs_reserved_C \long\def\xs_StrSplit_ii#1#2{% \let\xs_reserved_B\empty\def\xs_reserved_C{#2}\def\xs_reserved_D{#1}\gdef\groupID{}% \ifnum#1>0 @@ -759,7 +759,7 @@ {\ifx\xs_reserved_C\empty\xs_reserved_E\fi \edef\__temp{\def\noexpand\xs_reserved_B{\unexpanded\expandafter{\xs_reserved_B}}\def\noexpand\xs_reserved_C{\unexpanded\expandafter{\xs_reserved_C}}}% \expandafter\xs_exitallgroups\__temp - \xs_gobarg% mange l'appel récursif \xs_read_reserved_C dans \xs_read_reserved_C + \xs_gobarg% mange l'appel récursif \xs_read_reserved_C dans \xs_read_reserved_C } {}% }% @@ -770,8 +770,8 @@ \def\xs_StrSplit_iii#1#2{\let#1\xs_reserved_B\let#2\xs_reserved_C} % StrCut[n]{<texte>}{<motif>}\macroA\macroB -% \macroA reçoit ce qui se trouve avant la n ème occurrence <motif> dans <texte> -% \macroB reçoit ce qui est après cette n ème occurrence +% \macroA reçoit ce qui se trouve avant la n ème occurrence <motif> dans <texte> +% \macroB reçoit ce qui est après cette n ème occurrence \xs_newmacro*3\StrCut{1}{2}{0}{% \xs_ifempty{#3}% {\gdef\groupID{}\let\xs_reserved_C\empty\let\xs_reserved_E\empty @@ -794,7 +794,7 @@ \noexpand\decimalpart=\number\decimalpart\relax }% \expandafter\xs_exitallgroups\__temp - \xs_gobarg% stoppe la récursivité dans \xs_read_reserved_D + \xs_gobarg% stoppe la récursivité dans \xs_read_reserved_D } {\xs_eaddtomacro\xs_reserved_C{\xs_reserved_E}% }% @@ -807,7 +807,7 @@ \long\def\xs_StrCut_iii#1#2{\let#1\xs_reserved_C\let#2\xs_reserved_E} % De la chaine #1, renvoie ce qui se trouve entre les positions -% #2 et #3, unités syntaxiques aux positions compris ! +% #2 et #3, unités syntaxiques aux positions compris ! \xs_newmacro\StrMid{}{3}{1}{% \begingroup \noexploregroups @@ -821,21 +821,21 @@ \gdef\groupID{}% } -% supprime #2 unités syntaxiques à gauche dans la chaine #1 +% supprime #2 unités syntaxiques à gauche dans la chaine #1 \xs_newmacro\StrGobbleLeft{}{2}{1}{% \let\xs_reserved_E\relax \xs_StrSplit_ii{#2}{#1}% \xs_exparg\xs_assign_xstringresult{\xs_reserved_C}{#3}% } -% extrait de #1 la chaine à gauche de longueur #2 +% extrait de #1 la chaine à gauche de longueur #2 \xs_newmacro\StrLeft{}{2}{1}{% \let\xs_reserved_E\relax \xs_StrSplit_ii{#2}{#1}% \xs_exparg\xs_assign_xstringresult{\xs_reserved_B}{#3}% } -% supprime #2 unités syntaxiques à droite dans la chaine #1 +% supprime #2 unités syntaxiques à droite dans la chaine #1 \xs_newmacro\StrGobbleRight{}{2}{1}{% \xs_StrLen{#1}[\xs_reserved_D]% \let\xs_reserved_E\relax @@ -843,7 +843,7 @@ \xs_exparg\xs_assign_xstringresult{\xs_reserved_B}{#3}% } -% renvoie #2 unités syntaxiques à la droite de la chaine #1 +% renvoie #2 unités syntaxiques à la droite de la chaine #1 \xs_newmacro\StrRight{}{2}{1}{% \xs_StrLen{#1}[\xs_reserved_D]% \let\xs_reserved_E\relax @@ -858,10 +858,10 @@ \let\xs_atbegingroup\relax \def\xs_atendofgroup{\expandafter\endgroup\expandafter\decimalpart\number\decimalpart\relax}% \def\xs_atnextsyntaxunit{% - \ifnum\decimalpart=\xs_reserved_D% la n ième US est atteinte ? - \edef\__temp{\def\noexpand\xs_reserved_B{\unexpanded\expandafter{\xs_reserved_A}}}% on capture l'US en cours qui est celle cherchée + \ifnum\decimalpart=\xs_reserved_D% la n ième US est atteinte ? + \edef\__temp{\def\noexpand\xs_reserved_B{\unexpanded\expandafter{\xs_reserved_A}}}% on capture l'US en cours qui est celle cherchée \expandafter\xs_exitallgroups\__temp - \expandafter\xs_gobarg% stoppe la récursivité dans \xs_read_reserved_C + \expandafter\xs_gobarg% stoppe la récursivité dans \xs_read_reserved_C \fi }% \xs_read_reserved_C @@ -905,8 +905,8 @@ \def\restorecomparemode{\let\xs_comparecoeff\xs_saved_comparecoeff} % Compare les deux arguments #1 et #2 -% Renvoie 0 s'ils sont égaux et renvoie la -% position de la premiere unité syntaxiques différente sinon +% Renvoie 0 s'ils sont égaux et renvoie la +% position de la premiere unité syntaxiques différente sinon \xs_newmacro*2\StrCompare{}{2}{1}{% \def\xs_reserved_A{#1}% \def\xs_reserved_B{#2}% @@ -931,13 +931,13 @@ \xs_exparg\xs_returnfirstsyntaxunit{\xs_reserved_D}\xs_reserved_B \xs_ifx{\xs_reserved_B\xs_reserved_A} {\xs_exparg\xs_ifempty{\xs_reserved_A}% - {\xs_StrCompare_iii{##1}% les 2 unités syntaxiques sont égales, on renvoie la position + {\xs_StrCompare_iii{##1}% les 2 unités syntaxiques sont égales, on renvoie la position } - {\def\xs_next{\xs_exparg\xs_StrCompare_ii{\number\numexpr##1+1}}% les 2 unités syntaxiques sont égales et non vides, on recommence + {\def\xs_next{\xs_exparg\xs_StrCompare_ii{\number\numexpr##1+1}}% les 2 unités syntaxiques sont égales et non vides, on recommence \xs_exparg\xs_removefirstsyntaxunit{\xs_reserved_C}\xs_reserved_C \xs_exparg\xs_removefirstsyntaxunit{\xs_reserved_D}\xs_reserved_D }% - }% les 2 unités syntaxiques sont différentes : on renvoie la position + }% les 2 unités syntaxiques sont différentes : on renvoie la position {\xs_StrCompare_iii{##1}% }% \xs_next @@ -959,10 +959,10 @@ {\xs_assign_xstringresult{}{#3}% s'il ne reste plus rien, on renvoie vide } {\xs_exparg\xs_returnfirstsyntaxunit{\xs_reserved_C}\xs_reserved_D - \xs_ifx{\bgroup\xs_toks}% si la 1ère unité syntaxique est un groupe explicite + \xs_ifx{\bgroup\xs_toks}% si la 1ère unité syntaxique est un groupe explicite {\advance\decimalpart1 % on augmente le compteur - \xs_ifnum{\decimalpart=\xs_reserved_A\relax}% on est au groupe cherché lors de la profondeur courante ? - {\xs_ifx{\empty\xs_reserved_B}% on est à la profondeur maximale ? + \xs_ifnum{\decimalpart=\xs_reserved_A\relax}% on est au groupe cherché lors de la profondeur courante ? + {\xs_ifx{\empty\xs_reserved_B}% on est à la profondeur maximale ? {\xs_exparg\xs_assign_xstringresult{\xs_reserved_D}{#3}}% on renvoie ce groupe {\xs_exparg{\expandafter\xs_StrFindGroup_i\xs_reserved_D}{\xs_reserved_B}[#3]}% on recommence avec ce groupe et les profondeurs de recherche restantes } @@ -1003,7 +1003,7 @@ \def\xs_atbegingroup{\let\xs_reserved_B\empty}% \def\xs_atnextsyntaxunit{\xs_eeaddtomacro\xs_reserved_B{\xs_reserved_A}}% \def\xs_reserved_C{#2}% - \xs_StrExpand_i{#1}% Appel de la macro récursive + \xs_StrExpand_i{#1}% Appel de la macro récursive } {\def\xs_reserved_B{#2}% } @@ -1043,185 +1043,188 @@ H I S T O R I Q U E ------------------------------------------------------------------------------ -v1.0 4/7/2008 : - Package achevé. - 7/7/2008 : - Package publié sur CTAN. +v1.0 4/7/2008 : - Package achevé. + 7/7/2008 : - Package publié sur CTAN. ------------------------------------------------------------------------------ v1.1 15/8/2008 - - Le package ne nécessite plus LaTeX et est désormais utilisable sous + - Le package ne nécessite plus LaTeX et est désormais utilisable sous Plain eTeX. - Ajout des macros \IfInteger et \IfDecimal. - Pour cette dernière, la partie entière et la partie décimale sont - récupérables dans les compteurs \integerpart et \decimalpart. Ce - qu'il reste après qu'un caractère non attendu soit rencontré est + Pour cette dernière, la partie entière et la partie décimale sont + récupérables dans les compteurs \integerpart et \decimalpart. Ce + qu'il reste après qu'un caractère non attendu soit rencontré est dispo dans \xs_remainafterdecimal - Correction d'un bug dans \tokenize : - suppression de l'expansion avec \normalexpandarg pour éviter le bug - avec les lettres accentuées dans l'exemple : \tokenize\aa{éù} - - Amélioration du code de la plupart des macros. - - écriture d'une routine \xs_newmacro définissant les macros. - - Suppression de tous les compteurs grace à \numexpr. - - Nouvelles fonctionnalités internes dans : + suppression de l'expansion avec \normalexpandarg pour éviter le bug + avec les lettres accentuées dans l'exemple : \tokenize\aa{éù} + - Amélioration du code de la plupart des macros. + - écriture d'une routine \xs_newmacro définissant les macros. + - Suppression de tous les compteurs grace à \numexpr. + - Nouvelles fonctionnalités internes dans : \IfSubStr - ajout des chaines se trouvant avant et après l'occurrence testée + ajout des chaines se trouvant avant et après l'occurrence testée dans les sc \xs_behind_IfSubStr et \xs_before_IfSubStr \StrCount - a) ajout de ce qui se trouve après la dernière occurrence dans la + a) ajout de ce qui se trouve après la dernière occurrence dans la sc \xs_StrCount_afterlastocccur - b) la macro ne dépend plus d'aucune autre + b) la macro ne dépend plus d'aucune autre ------------------------------------------------------------------------------ v1.2 23/8/2008 - - Amélioration du code de \StrMid \StrGobbleLeft, \StrLeft, - \StrGobbleRight et \StrRight à l'aide de la nouvelle macro + - Amélioration du code de \StrMid \StrGobbleLeft, \StrLeft, + \StrGobbleRight et \StrRight à l'aide de la nouvelle macro \xs_StrSplit_i - Nouveau test \IfStrEq qui compare 2 chaines - Nouveau test \IfEq qui compare 2 chaines (ou 2 nombres si les 2 chaines contiennent un nombre) - Correction d'un bug dans \xs_formatnumber. La macro n'envisageait pas le - cas où son argument était vide ce qui faiasait planter + cas où son argument était vide ce qui faiasait planter \IfDecimal{}{V}{F} et \IfInteger{}{V}{F} ------------------------------------------------------------------------------ v1.3 21/9/2008 - - Amélioration du code, mise en place de récursivités terminales dans - toutes les macros récursives, simplification de \xs_TestEqual en + - Amélioration du code, mise en place de récursivités terminales dans + toutes les macros récursives, simplification de \xs_TestEqual en utilisant \ifx - Nouvelles macros \IfStrEqCase et \IfEqCase - Teste si une chaîne est égale à plusieurs chaines données et - exécute un code spécifique - - Création de la macro publique \StrSplit - Coupe la chaine en 2 à une position donnée + Teste si une chaîne est égale à plusieurs chaines données et + exécute un code spécifique + - Création de la macro publique \StrSplit + Coupe la chaine en 2 à une position donnée - Nouvelle macro \StrCompare - Compare 2 chaînes et renvoie la position du 1er caractère différent. - Renvoie 0 si elles sont égales. + Compare 2 chaînes et renvoie la position du 1er caractère différent. + Renvoie 0 si elles sont égales. ------------------------------------------------------------------------------ v1.3a 29/9/2008 - Correction d'un bug : \expandafter#1 dans les macros \IfSubStrBefore et \StrBetween qui buggue si #1 est un nombre > 9 ! - - Ré écriture de \xs_returnfirstsyntaxunit et \xs_gobarg qui - deviennent purement développables. - - Ré écriture de \StrLen + - Ré écriture de \xs_returnfirstsyntaxunit et \xs_gobarg qui + deviennent purement développables. + - Ré écriture de \StrLen - Nouvelle macro interne \xs_cutafteroccur - Coupe la chaine après la nième occurrence d'une sous chaine. - - Code amélioré de \StrMid, \StrLeft, \StrGobbleLeft, \StrRight, - \StrGobbleRight grace à \xs_cutafteroccur + Coupe la chaine après la nième occurrence d'une sous chaine. + - Code amélioré de \StrMid, \StrLeft, \StrGobbleLeft, \StrRight, + \StrGobbleRight grace à \xs_cutafteroccur ------------------------------------------------------------------------------ v1.4 4/11/2008 - - xstring traite ses arguments par unité syntaxique, et donc toutes les - macros internes ont été ré-écrites à cette fin. - - Le manuel a été ré-écrit, rendu plus clair et mieux structuré. - - Nouvelle fonctionnalité : \expandarg - le 1er lexème de chaque argument est 1-développé avant que la - macro ne soit appelée. Si un argument comporte plus qu'1 lexème, - il faut passer par \scancs*[1] pour 1-développer toutes les unités + - xstring traite ses arguments par unité syntaxique, et donc toutes les + macros internes ont été ré-écrites à cette fin. + - Le manuel a été ré-écrit, rendu plus clair et mieux structuré. + - Nouvelle fonctionnalité : \expandarg + le 1er lexème de chaque argument est 1-développé avant que la + macro ne soit appelée. Si un argument comporte plus qu'1 lexème, + il faut passer par \scancs*[1] pour 1-développer toutes les unités syntaxiques. - Correction de 2 erreurs dans le manuel anglais : 0 est la valeur par - défaut dans \StrSubstitute et \StrDel - - Cohérence dans les nom des séquences de contrôles temporaires qui - sont désormais : \xs_reserved_A à \xs_reserved_E + défaut dans \StrSubstitute et \StrDel + - Cohérence dans les nom des séquences de contrôles temporaires qui + sont désormais : \xs_reserved_A à \xs_reserved_E ------------------------------------------------------------------------------ v1.4a 12/11/2008 - - Correction d'un bug dans \xs_StrSplit dans le cas où l'argument - numérique est <1 : la 1ere coupure doit être vide et le seconde doit - être égale à l'argument. + - Correction d'un bug dans \xs_StrSplit dans le cas où l'argument + numérique est <1 : la 1ere coupure doit être vide et le seconde doit + être égale à l'argument. ------------------------------------------------------------------------------ v1.4b 16/11/2008 - Correction de 2 bugs dans \xs_returnfirstsyntaxunit ------------------------------------------------------------------------------ v1.5 31/12/2008 - - Nouvelles fonctionnalités dans la recherche de groupes par un - identificateur caractérisant leur imbrication. Implémentation de : + - Nouvelles fonctionnalités dans la recherche de groupes par un + identificateur caractérisant leur imbrication. Implémentation de : 1) \StrFindGroup 2) \groupID - - Ajout des nouvelles macros génériques \xs_read_reserved_C et + - Ajout des nouvelles macros génériques \xs_read_reserved_C et \xs_read_reserved_D - Correction d'un bug dans \StrSplit : \StrSplit{{a}bc}{1}[\truc] faisait - que \truc contenait «a{a}». - - Correction d'un bug dans \xs_newmacro : l'argument optionnel était - détokénisé à tort dans les macros étoilées. - - Dans \xs_newmacro, on doit choisir le numéro du dernier argument devant - être détokénisé dans le cas d'une macro étoilée (sachant que + que \truc contenait «a{a}». + - Correction d'un bug dans \xs_newmacro : l'argument optionnel était + détokénisé à tort dans les macros étoilées. + - Dans \xs_newmacro, on doit choisir le numéro du dernier argument devant + être détokénisé dans le cas d'une macro étoilée (sachant que l'argument optionnel ne l'est jamais) ------------------------------------------------------------------------------ v1.5a 09/2/2009 - Nouvelle macro \StrExpand, sensible au mode d'exploration. La macro est - indépendante du mode d'exploration et dispose de ses propres commandes + indépendante du mode d'exploration et dispose de ses propres commandes d'exploration : \expandingroups et \noexpandingroups - - Ré-écriture de \scancs, qui devient triviale puisque dépendant de - \StrExpand. Il n'y a plus de version étoilée et désormais, \scancs + - Ré-écriture de \scancs, qui devient triviale puisque dépendant de + \StrExpand. Il n'y a plus de version étoilée et désormais, \scancs est sensible au mode d'exploration. - Correction d'un bug dans \IfInteger : \IfInteger{2.0}{V}{F} affichait F - Correction de bugs : mettre \let\xs_reserved_E\relax avant d'appeler \xs_StrSplit_i - Suppression des messages d'erreur, de warning et d'info. xstring devient donc silencieux ;) - - Passage de 3 à 2 compteurs - - Le manuel est désormais plus coloré, en espérant qu'il sera un peu - plus agréable à lire ! + - Passage de 3 à 2 compteurs + - Le manuel est désormais plus coloré, en espérant qu'il sera un peu + plus agréable à lire ! ------------------------------------------------------------------------------ v1.5b 13/3/2009 - Modification d'un grand nombre de macros de telle sorte que vraiment - n'importe quel code peut désormais être placé dans les arguments des - macros (comme par exemple des \if, \ifx ou autre, même sans leur \fi, ce - qui n'était pas possible jusqu'alors) + n'importe quel code peut désormais être placé dans les arguments des + macros (comme par exemple des \if, \ifx ou autre, même sans leur \fi, ce + qui n'était pas possible jusqu'alors) ------------------------------------------------------------------------------ v1.5c 05/6/2009 - Correction d'un bug dans \IfBeginWith : il faut appeler \xs_returnfirstsyntaxunit pour l'argument #2 puis pour l'argument #1 et - non pas l'inverse pour que \xs_toks reflète ce qui se trouve dans #1 - - Correction d'un bug dans \xs_returnfirstsyntaxunit au cas où #1 commence - par un espace : mettre \xs_toks à 0 + non pas l'inverse pour que \xs_toks reflète ce qui se trouve dans #1 + - Correction d'un bug dans \xs_returnfirstsyntaxunit au cas où #1 commence + par un espace : mettre \xs_toks à 0 - Correction d'un bug dans \xs_returnfirstsyntaxunit : \xs_returnfirstsyntaxunit{{}}\truc - faisait que \truc se développait en un espace. - - Correction d'un bug dans \xs_removefirstsyntaxunit où le cas + faisait que \truc se développait en un espace. + - Correction d'un bug dans \xs_removefirstsyntaxunit où le cas \xs_removefirstsyntaxunit{ {b}}\truc - donnait \truc se développant en «b» au lieu de «{b}». + donnait \truc se développant en «b» au lieu de «{b}». ------------------------------------------------------------------------------ v1.5d 28/3/2010 - Correction d'un bug dans \IfInteger : \afterinteger ne donnait pas le - bon résultat. Par exemple avec 1.23 il renvoyait {} au lieu de {.23} - - \xs_formatnumber ne detokenize plus ses arguments (que m'est-il passé - par la tête pour que je code un truc comme ca ?), et donc + bon résultat. Par exemple avec 1.23 il renvoyait {} au lieu de {.23} + - \xs_formatnumber ne detokenize plus ses arguments (que m'est-il passé + par la tête pour que je code un truc comme ca ?), et donc \afterinteger et \xs_afterdecimal ont des tokens ayant le bon catcode ------------------------------------------------------------------------------ v1.6 24/10/2012 - - Correction d'un bug dans \xs_cutafteroccur au cas où #3<1 + - Correction d'un bug dans \xs_cutafteroccur au cas où #3<1 - \IfDecimal ne \detokenize plus l'argument. - Nouvelle version de \tokenize qui enlevait les accolades si son argument - était entre accolades + était entre accolades - Nouvelle macro \StrCut - - \xs_cutafteroccur_i ne produit plus d'espace indésirable si #3 était - évalué par \numexpr + - \xs_cutafteroccur_i ne produit plus d'espace indésirable si #3 était + évalué par \numexpr ------------------------------------------------------------------------------ v1.7 13/1/2013 - Correction d'un manque de rigueur dans les assignations concernant - \groupID : elles sont toutes globales désormais + \groupID : elles sont toutes globales désormais - Les macros de xstring sont \long ------------------------------------------------------------------------------ v1.7a 28/2/2013 - Correction d'un espace parasite dans \xs_removefirstsyntaxunit ------------------------------------------------------------------------------ v1.7b 29/7/2013 - - La date contenue dans \xstringdate est désormais conforme + - La date contenue dans \xstringdate est désormais conforme ------------------------------------------------------------------------------ v1.7c 13/10/2013 - - les macros impliquées dans \IfStrCase et \IfStrEqCase sont désormais \long + - les macros impliquées dans \IfStrCase et \IfStrEqCase sont désormais \long ------------------------------------------------------------------------------ v1.8 07/12/2018 - - affectations globales supprimées (sauf pour \groupID) afin de ne pas + - affectations globales supprimées (sauf pour \groupID) afin de ne pas surcharger la pile de sauvegarde - nettoyage du code, corrections de lourdeurs et maladresses ------------------------------------------------------------------------------ v1.81 09/12/2018 - - bug dans \IfInteger et \IfDecimal, la macro \xs_afterdecimal est indéfinie - et doit être remplacée par \afterdecimal + - bug dans \IfInteger et \IfDecimal, la macro \xs_afterdecimal est indéfinie + et doit être remplacée par \afterdecimal ------------------------------------------------------------------------------ v1.82 01/02/2019 - \xs_testopt n'est pas longue et provoque un bug dans \xs_IfStrCase et \xs_IfStrCase lorsque #1 contient \par : \xs_testopt reste courte et - \xs_IfStringCase a été modifiée pour que cela fonctionne. + \xs_IfStringCase a été modifiée pour que cela fonctionne. ------------------------------------------------------------------------------ v1.83 06/02/2019 - - mauvaise approche et mauvais fix dans la v1.82 : \xs_testopt devient - longue, pas le choix (et donc aussi \xs_ifnxttok)
\ No newline at end of file + - mauvaise approche et mauvais fix dans la v1.82 : \xs_testopt devient + longue, pas le choix (et donc aussi \xs_ifnxttok) +------------------------------------------------------------------------------ +v1.84 21/07/2021 + - encodage du fichier xstring.tex en UTF-8 |