diff options
author | Norbert Preining <norbert@preining.info> | 2023-11-17 03:02:29 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2023-11-17 03:02:29 +0000 |
commit | d91bb5cad66508ec34d77ea60c0a02c79308edef (patch) | |
tree | 69c363099e912a77d55b67d891020bcc1f407d80 /macros/optex/base | |
parent | e0db3f0709a737e7258fd40a7cbfe9a461ea0756 (diff) |
CTAN sync 202311170302
Diffstat (limited to 'macros/optex/base')
32 files changed, 1652 insertions, 283 deletions
diff --git a/macros/optex/base/basic-macros.opm b/macros/optex/base/basic-macros.opm index 9227505678..f2047cadf0 100644 --- a/macros/optex/base/basic-macros.opm +++ b/macros/optex/base/basic-macros.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \sdef {Basic macros for OpTeX <2023-01-22>} % preloaded in format +\_codedecl \sdef {Basic macros for OpTeX <2023-11-11>} % preloaded in format \_doc ------------------------------ \`\bgroup`, \`\egroup`, \`\empty`, \`\space`, and \`\null` @@ -56,12 +56,20 @@ \_public \sdef \sxdef \slet ; \_doc ------------------------------ - \`\adef` `{<char>}{<body>}` puts the <char> as active character and defines it - as `{<body>}`. You can declare a macro with parameters too. For example - `\adef @#1{...#1...}`. + \`\adef` `<char>{<body>}` defines active `<char>` as <body> and then + puts the <char> as active character. I.e. the `<body>` can include the + <char> as non-active charter (if it is non-active before `\adef`). + For example `\adef ?{\,?}`. + If the character is special, you can escape it, for example `\adef\%{...}`. + The space can be declared by `\adef{ }{<body>}`. + You can declare a macro with parameters too, for example + `\adef @#1{...#1...}`. You can use prefixes `\protected`, `\global`, + `\long` before `\adef`, they behave like prefixes before `\def`. \_cod ------------------------------ -\_def \_adef #1{\_catcode`#1=13 \_begingroup \_lccode`\~=`#1\_lowercase{\_endgroup\_def~}} +\_def\_adef#1#2#{\_adefA{#1}{#2}} +\_def\_adefA#1#2#3{\_ea\_def\_directlua{tex.cprint(13,"\_luaescapestring{\_csstring#1}")}#2{#3}% + \_catcode`#1=13 } \_public \adef ; \_doc ------------------------------ @@ -142,6 +150,7 @@ \_endcode % ------------------------------------- +2023-11-11: \adef reimplemented, \protected, \long, \global allowed before \adef 2023-01-22: \trycs: afterfi used for second parameter 2022-11-22: \_banner definition moved here 2022-11-18: \ahead introduced diff --git a/macros/optex/base/bib-iso690.opm b/macros/optex/base/bib-iso690.opm index fcdbd5d48d..5595d65877 100644 --- a/macros/optex/base/bib-iso690.opm +++ b/macros/optex/base/bib-iso690.opm @@ -1,6 +1,6 @@ % This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \_undefined {BIB style (iso690) <2023-04-22>} % loaded on demand by \usebib +\_codedecl \_undefined {BIB style (iso690) <2023-09-13>} % loaded on demand by \usebib \_ifx\_optexbibstyle\_undefined \_errmessage {This file can be read by: \_string\usebib/? (iso690) bibfiles command only} @@ -116,7 +116,7 @@ \_bibmark=\_ea{\_tmp}% } \_def\_createbibmark #1;#2,#3;#4,#5\_fin{% #1=year #2=LastName #3=FirstName #4=nextAuthor - #2\_ifx^#4^\_else \_Mtext{bib.etal}\_fi, #1% + #2\_ifx^#4^\_else \_Mtext{bib.etal}\_fi \_ifx^#1^\_else, #1\_fi } \_doc ----------------------------- @@ -151,24 +151,10 @@ } \_doc ----------------------------- - Non-standard field names. - \_cod ----------------------------- - -\_CreateField {ednote} -\_CreateField {citedate} -\_CreateField {numbering} -\_CreateField {isbn} -\_CreateField {issn} -\_CreateField {doi} -\_CreateField {url} -\_CreateField {bibmark} - - \_doc ----------------------------- Sorting. \_cod ----------------------------- -\_SortingOrder{name,year}{lfvj} -\_SpecialSort {key} +\_fieldalias {key} {sortedby} \_doc ----------------------------- Supporting macros. @@ -305,9 +291,21 @@ \_bprintb [url] {\_preurl\_url{##1}. }{}% } \_sdef{_print:phdthesis}{\_def\_thesistype{\_Mtext{bib.phdthesis}}\_cs{_print:thesis}} -\_sdef{_print:mastershesis}{\_def\_thesistype{\_Mtext{bib.masthesis}}\_cs{_print:thesis}} +\_sdef{_print:mastersthesis}{\_def\_thesistype{\_Mtext{bib.masthesis}}\_cs{_print:thesis}} \_sdef{_print:bachelorsthesis}{\_def\_thesistype{\_Mtext{bib.bachthesis}}\_cs{_print:thesis}} +\_sdef{_print:online}{% + \_bprintb [!author] {\_doauthor1{##1}\:\ }{}% + \_bprintb [title] {{\_em##1}\_bprintc\_titlepost{\:\ *}\_bprintv[howpublished]{}{\:}\ }% + {\_bibwarning}% + \_bprinta [howpublished] {[*].\ }{}% + \_bprinta [ednote] {\_prepareednote*\_bprintv[citedate]{}{.}\ }{}% + \_bprinta [year] {}{}% + \_bprinta [accessed] {\_docitedate*///\_relax.\ }{\_bibwarning}% + \_bprintb [doi] {\_predoi DOI \_ulink[http://dx.doi.org/##1]{##1}.\ }{}% + \_bprintb [url] {\_preurl\_url{##1}. }{\_bibwarning}% +} + \_sdef{_print:generic}{% \_bprintb [!author] {\_doauthor1{##1}\:\ }{\_bibwarning}% \_bprintb [title] {{\_em##1}\_bprintc\_titlepost{\:\ *}\_bprintv[howpublished]{}{\:}\ }% @@ -784,6 +782,12 @@ There are nearly equivalent entries: `@BACHELORSTHESIS`, `@MASTERSTHESIS` and automatically. The type field is optional in this case. If it is used then it has precedence before the default setting. +\secccc The @ONLINE entry + +It is intended for online publications. + +Fields: author, title(!), howpublished, ednote, publisher, accessed, doi, url(!), note. + \secccc The @MISC entry It is intended for various usage. @@ -835,19 +839,20 @@ yearprint value) is also used in the text-oriented bib-marks when `\nonumcitations` is set. If you have some problems with name sorting, you can use the hidden field -`key`, which is used for sorting instead of the \"Lastname Firstname(s)" -of authors. If the `key` field is unset then the \"Lastname Firstname(s)" +`sortedby` (or `key` field with the same effect). +It can be used for sorting instead of the \"Lastname Firstname(s)" +of the first author. If the `sortedby` field is unset then the \"Lastname Firstname(s)" is used for sorting normally. Example: \begtt author = "Světla Čmejrková", -key = "Czzmejrkova Svetla", +sortedby = "Czzmejrkova Svetla", \endtt This entry is now sorted between C and D. The norm recommends placing the auto-citations at the top of the list of -references. You can do this by setting `key = "@"`, to each entry with your +references. You can do this by setting `sortedby = "@"`, to each entry with your name because the `@` character is sorted before `A`. @@ -928,6 +933,8 @@ Other options in the option field are silently ignored. \_endinput +2023-09-13 ... \_createbibmark: no comma if year is missing +2023-06-23 ... @ONLINE entry introduced 2023-04-22 ... incollection: typo corrected 2023-03-25 ... \_createbibmark introduced 2022-05-10 ... \. -> \:, collision with \oldaccents fixed. diff --git a/macros/optex/base/bib-simple.opm b/macros/optex/base/bib-simple.opm index e61e94d7e2..c70bb12be7 100644 --- a/macros/optex/base/bib-simple.opm +++ b/macros/optex/base/bib-simple.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \_undefined {BIB style (simple) <2023-04-22>} % loaded on demand by \usebib +\_codedecl \_undefined {BIB style (simple) <2023-09-13>} % loaded on demand by \usebib \_ifx\_optexbibstyle\_undefined \_errmessage {This file can be read by: \_string\usebib/? (simple) bibfiles command only} @@ -39,7 +39,7 @@ \_edef\_tmp{\_ea\_createbibmark\_expanded{\_tmp;\_authlist;,;,;,;}\_fin}\_fi \_bibmark=\_ea{\_tmp}% } -\_def\_createbibmark#1;#2,#3\_fin{#2, #1} +\_def\_createbibmark#1;#2,#3\_fin{#2\_ifx^#1^\_else, #1\_fi} \_def\_preurl{\_hfil\_break} \_def\_Inclause{In:~} @@ -156,6 +156,14 @@ \_bprinta [institution] {*.\ }{}% \_bprintb [url] {\_preurl\_url{##1}. }{}% } +\_sdef{_print:online}{% + \_bprinta [!author] {*.\ }{}% + \_bprintb [title] {{\_em##1}\:\ }{}% + \_bprinta [howpublished] {*.\ }{}% + \_bprinta [institution] {*.\ }{}% + \_bprinta [series] {*.\ }{}% + \_bprintb [url] {\_preurl\_url{##1}. }{\_bibwarning}% +} \_sdef{_print:misc}{% \_bprinta [!author] {*.\ }{}% \_bprintb [title] {{\_em##1}\:\ }{}% diff --git a/macros/optex/base/cite-bib.opm b/macros/optex/base/cite-bib.opm index 9dc32a2632..805b84de03 100644 --- a/macros/optex/base/cite-bib.opm +++ b/macros/optex/base/cite-bib.opm @@ -1,4 +1,4 @@ -%% This is part of the OpTeX project, see http://petr.olsak.net/optex +% This is part of the OpTeX project, see http://petr.olsak.net/optex \_codedecl \cite {Cite, Biblioraphy <2021-04-13>} % preloaded in format @@ -97,7 +97,7 @@ \_cod ----------------------------- \_def\_citeA #1#2,{\_if#1,\_else - \_if *#1\_addcitelist{*}\_ea\_skiptorelax \_fi + \_if *#1\_addcitelist{*}\_sxdef{_bib:\_bibp*}{}\_ea\_skiptorelax \_fi \_ifcsname _bib:\_bibp#1#2\_endcsname \_else \_addcitelist{#1#2}% \_opwarning{{\_the\_bibpart} \_noexpand\cite [#1#2] unknown. Try to TeX me again}\_openref @@ -125,7 +125,7 @@ distinguished by <bibpart>, the \`\_addcitelist``{<label>}` macro must add the <label> to given `\_ctlst:<bibpart>/`.\nl When `\_addcitelist` is processed before \^`\usebib`, - then \`\_citeI``[<label>]` is added. \^`\usebib` will use this list for selecting + then \^`\_citeI``[<label>]` is added. \^`\usebib` will use this list for selecting right records from `.bib` file. Then \^`\usebib` sets `\_ctlst:<bibpart>/` to `\_write`.\nl If `\_addcitelist` is processed after \^`\usebib`, then diff --git a/macros/optex/base/colors.opm b/macros/optex/base/colors.opm index 36afcb3862..e43a40c779 100644 --- a/macros/optex/base/colors.opm +++ b/macros/optex/base/colors.opm @@ -381,6 +381,10 @@ color data. This mapping is used just before each `\shipout` in output routine. The \^`\_preshipout` pseudo-primitive is used here, it converts attribute values to internal PDF commands for selecting colors. +The concept with color attributes has one limitation: the colors cannot be changed +inside a ligature unless the ligature is broken manually. It means that +`{\Red f}i` doesn't lead to the expected result but `{\Red f\null}i` does. + \secc Color mixing The color mixing processed by the \^`\colordef` is done in the subtractive color diff --git a/macros/optex/base/f-clara.opm b/macros/optex/base/f-clara.opm new file mode 100644 index 0000000000..1410965dd2 --- /dev/null +++ b/macros/optex/base/f-clara.opm @@ -0,0 +1,24 @@ +%% This is part of the OpTeX project, see http://petr.olsak.net/optex + +\_famdecl [Clara] \Clara {Clara, a serif font family} + {\caps} {\rm \bf \it \bi} + {XITSMath} {[clarar]} + {\_def\_fontnamegen {[clara\_currV]:\_capsV\_fontfeatures}} + +\_wlog{\_detokenize{% +Modifiers:^^J + \caps ...... caps & small caps (only \rm with simple alphabet!)^^J +}} + +% Modes +\_moddef \resetmod {\_fsetV caps={} \_fvars r b i bi } +\_moddef \caps {\_fsetV caps=+smcp; } % onum; set by smcp; feature +\_moddef \nocaps {\_fsetV caps={} } + +\_initfontfamily % New font family must be initialized + +\_loadmath {[XITSMath-Regular]} +\_loadboldmath {[XITSMath-Bold]} \to {[XITSMath-Regular]} + +\_endcode + diff --git a/macros/optex/base/f-culmus.opm b/macros/optex/base/f-culmus.opm new file mode 100644 index 0000000000..66d2952d3f --- /dev/null +++ b/macros/optex/base/f-culmus.opm @@ -0,0 +1,25 @@ +%% This is part of the OpTeX project, see http://petr.olsak.net/optex + +\_famdecl [Culmus] \Culmus {Hebrew fonts from the Culmus project} + {\roman \sans \mono} {\rm \bf \it \bi} {} + {[DavidCLM-Medium]} + {\_def\_fontnamegen {[\_subfamV CLM-\_currV]:script=hebr;\_fontfeatures}} + +\_wlog{\_detokenize{% +script=hebr is set by default,^^J +use e.g \setff{script={}}\rm^^J +to suppress this.^^J +Modifiers (subfamilies):^^J + \roman ...... \rm, \it = Medium, \bf, \bi = Bold (Roman)^^J + \sans ...... \rm, \it = Light, \bf, \bi = Bold (Sans)^^J + \mono ...... \rm, \it = Book, \bf, \bi = Bold (Mono)^^J +}} + +% modifiers (they select a subfamily) +\_moddef \resetmod {\_fsetV subfam=David \_fvars Medium Bold MediumItalic BoldItalic } +\_moddef \roman {\_fsetV subfam=David \_fvars Medium Bold MediumItalic BoldItalic } +\_moddef \sans {\_fsetV subfam=Nachlieli \_fvars Light Bold LightOblique BoldOblique } +\_moddef \mono {\_fsetV subfam=MiriamMono \_fvars Book Bold BookOblique BoldOblique } +\_initfontfamily % new font family must be initialized + +\_endcode diff --git a/macros/optex/base/f-fraunces.opm b/macros/optex/base/f-fraunces.opm new file mode 100644 index 0000000000..7684dbc4e8 --- /dev/null +++ b/macros/optex/base/f-fraunces.opm @@ -0,0 +1,69 @@ +%% This is part of the OpTeX project, see http://petr.olsak.net/optex + +\_famdecl [Fraunces] \Fraunces {Display, "Old Style" soft serif typeface} + {\wonky} {\rm \bf \it \bi} {Bonum} + {[Fraunces-VariableFont_SOFT,WONK,opsz,wght]} + {\_def\_fontnamegen {[Fraunces-\_currV VariableFont_SOFT,WONK,opsz,wght]:-liga;% + axis={wght=\_f_getwght{+300},opsz=\_the\_f_opsz,soft=\_the\_f_soft};\_wonkyV\_fontfeatures}} + +% \_f_getwght{+300} returns \the\wght but if \bf or \bi is processed then it returns \wght+300. +\_def \_f_getwght#1{\_if b\_ea\_ignoresecond\_famv \_the\_numexpr \_f_wght#1\_relax \_else \_the\_f_wght \_fi} + +\_wlog{\_detokenize{% +Modifiers:^^J + \wonky ..... alternative strokes^^J + \thin ...... \rm, \it = Thin, \bf, \bi = Normal^^J + \light ..... \rm, \it = Light, \bf, \bi = Medium^^J + \normal .... \rm, \it = Normal, \bf, \bi = Bold^^J + \bolder .... \rm, \it = Medium, \bf, \bi = Black^^J% +Variable font parameters:^^J + \wght ...... 100--1000 (default 400): weight of the strokes^^J + \opsz ...... 6--144 (default 14): optical size modifiation^^J + \ssoft ..... 0--100 (default 0): softness of serifs^^J + Use \wght=650 \ssoft=50 (for example). It acts like others font modifiers.^^J% +Extended variants:^^J + \tf \ti .... Thin, ThinItalic^^J + \lf \li .... Light, LightItalic^^J + \mf \mi .... Medium, MediumItalic^^J + \kf \ki .... Black, BlackItalic^^J +}} + +\_ifx\_f_wght\_undefined \_newcount\_f_wght \_f_wght=400 \_newpublic \_let\wght=\_f_wght \_fi +\_ifx\_f_opsz\_undefined \_newcount\_f_opsz \_f_opsz=14 \_newpublic \_let\opsz=\_f_opsz \_fi +\_ifx\_f_soft\_undefined \_newcount\_f_soft \_f_soft=0 \_newpublic \_let\ssoft=\_f_soft \_fi + +\_moddef \resetmod {\_fsetV wonky={} \_fvars {} {} Italic- Italic- } +\_moddef \wonky {\_fsetV wonky=+ss01; } +\_moddef \thin {\_f_wght=100 } +\_moddef \light {\_f_wght=250 } +\_moddef \normal {\_f_wght=400 } +\_moddef \medium {\_f_wght=550 } +\_let\_thinM=\thin \_let\_lightM=\light \_let\_mediumM=\medium + +\_famvardef \tf {\_thinM \_rm} +\_famvardef \ti {\_thinM \_it} +\_famvardef \lf {\_lightM \_rm} +\_famvardef \li {\_lightM \_it} +\_famvardef \mf {\_mediumM \_rm} +\_famvardef \mi {\_mediumM \_it} +\_famvardef \kf {\_mediumM \_bf} +\_famvardef \ki {\_mediumM \_bi} + +\_initfontfamily % new font family must be initialized + +\_loadmath {[texgyrebonum-math]} + +\_endcode + +This is an example of a font-file used for a variable fonts. + +\begitems +* Declare counters with the same names as parameters of axis. +* Use `\_ifx\_...\_undefined` in order to more font-files with variable fonts can be loaded. +* Use `axis={...}` in font features area in the `\_fontnamegen` macro. +* Print about axis parameters of given font to the log using `\_wlog`. +* The `\_f_getwght` macro should be declared same in all font-files with variable fonts. + It enables \bf and \bi variants implemented as the given shift of the current wght parameter. +* You can declare more variants by `\famvardef`. +* You can declare font modifiers and font variants using values of axis parameters. +\enditems diff --git a/macros/optex/base/f-heuristica.opm b/macros/optex/base/f-heuristica.opm index bca6c0f318..d231774729 100644 --- a/macros/optex/base/f-heuristica.opm +++ b/macros/optex/base/f-heuristica.opm @@ -3,14 +3,15 @@ \_famdecl [Heuristica] \Heuristica {Extends the Utopia font} {} {\rm \bf \it \bi} {} {[Heuristica-Regular]} - {\_def\_fontnamegen {[Heuristica-\_currV]:\_capsV\_fontfeatures}} + {\_def\_fontnamegen {[Heuristica-\_currV]:script=latn;\_capsV\_fontfeatures}} \_wlog{\_detokenize{% No modifiers.^^J -% \caps ...... caps & small caps^^J + \caps ...... caps & small caps (\rm only)^^J }} \_moddef \resetmod {\_fsetV caps={} \_fvars regular bold italic bolditalic } +\_moddef \caps {\_fsetV caps=+smcp;\_ffonum; } \_initfontfamily % new font family must be initialized diff --git a/macros/optex/base/f-oldstandard.opm b/macros/optex/base/f-oldstandard.opm new file mode 100644 index 0000000000..68d01da26c --- /dev/null +++ b/macros/optex/base/f-oldstandard.opm @@ -0,0 +1,22 @@ +%% This is part of the OpTeX project, see http://petr.olsak.net/optex + +\_famdecl [OldStandard] \Oldstandard {inspired by a typeface most commonly used in old books} + {\caps} {\rm \bf \it \bi} {} + {[OldStandard-Regular]} + {\_def\_fontnamegen {[OldStandard-\_currV]:script=latn;\_capsV\_fontfeatures}} + +\_wlog{\_detokenize{% +Modifier:^^J + \caps ...... caps & small caps^^J +}} + +\_moddef \resetmod {\_fsetV caps={} \_fvars Regular Bold Italic BoldItalic } +\_moddef \caps {\_fsetV caps=+smcp;\_ffonum; } + +\_initfontfamily % new font family must be initialized + +\_endcode + +See the file `f-heros.opm` for information about principles of such +font-macro-files. + diff --git a/macros/optex/base/fams-ini.opm b/macros/optex/base/fams-ini.opm index adfc1050c5..6dc19ca9b1 100644 --- a/macros/optex/base/fams-ini.opm +++ b/macros/optex/base/fams-ini.opm @@ -139,9 +139,16 @@ { -,\caps: {\rm\bf\it\bi} } \_famalias [Baskervald ADF] \_famalias [ADFBaskerville] +\_famfrom {Undercase Type https://undercase.xyz/} +\_faminfo [Fraunces] {Display, old-style soft serif typeface} {f-fraunces} + { -: {\tf\ti\lf\li\rm\it\mf\mi\bf\bi\kf\ki} + \wonky: {\rm\it} + \ssoft=70: {\rm\it} + } + \_famfrom {Andrey V. Panov} \_faminfo [Heuristica] {Extends the Utopia font} {f-heuristica} - { -: {\rm\bf\it\bi} } + { -: {\rm\bf\it\bi} \caps: {\rm} } \_faminfo [Erewhon] {Derived from Heuristica with slanted variants} {f-erewhon} { -: {\rm\bf\it\bi\sl\bs} \caps: {\rm\bf\it\bi} } @@ -252,6 +259,18 @@ \_faminfo [Inconsolata] {A monospaced font for code listing} {f-inconsolata} { -,\narrow: {\rm\bf} } +\_famfrom {Alexey Kryukov} +\_faminfo [OldStandard] {inspired by a typeface most commonly used in old books} {f-oldstandard} + { -,\caps: {\rm\bf\it\bi} } + +\_famfrom {Séamas Ó Brógáin} +\_faminfo [Clara] {Clara, a serif font family} {f-clara} + { -: {\rm\bf\it\bi} \caps: {\rm} } + +\_famfrom {Maxim Iorsh} +\_faminfo [Culmus] {Hebrew roman, sans and mono fonts from the Culmus project} {f-culmus} + {\roman,\sans,\mono: {\rm\bf\it\bi}} + \_endcode Once you have prepared a font family file with the name `f-<famname>.opm` and diff --git a/macros/optex/base/fonts-catalog.opm b/macros/optex/base/fonts-catalog.opm index 893c731df0..1ea403b9c8 100644 --- a/macros/optex/base/fonts-catalog.opm +++ b/macros/optex/base/fonts-catalog.opm @@ -1,13 +1,13 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \_undefined {Font catalogue <2023-03-09>} % loaded on demand by \fontfam[catalog] +\_codedecl \_undefined {Font catalogue <2023-06-04>} % loaded on demand by \fontfam[catalog] \_tracinglostchars=1 % only to log file \_initunifonts \_raggedbottom \_begingroup -\_istoksempty\_catalogmathsample \_iftrue \_noloadmath \_fi +\_istoksempty\_catalogmathsample \_iftrue \_noloadmath \_else \_input{unimath-codes.opm}\_fi \_global\_font\_ttfixed=[LMMono10-Regular]\_relax \_fontlet\_smalltt=\_ttfixed at7pt \_suppressfontnotfounderror=1 @@ -26,6 +26,7 @@ \_def\_faminfo [#1]#2#3#4{% \_bgroup + \_rightskip=0sp plus 1fill \_lowercase{\_edef\_famname{\_ea\_removespaces #1 {} }}% \_edef\_act{\_noexpand\_isinlist{,\_cataloglist,}{,\_famname,}}\_act \_iftrue \def\_cataloglist{}\_fi @@ -33,12 +34,14 @@ \_iftrue \def\_cataloglist{.}\_fi \_ifx\_cataloglist\_empty \_ifx^#4^\_else - \_bigskip {\_ttfixed\_string\fontfam [#1] -- (#2)\_par} + \_the\_catalognextfam + {\_ttfixed\_string\fontfam [#1] -- (#2)\_par}\_nobreak \_input #3.opm - \_ifexistfam \_nobreak\_medskip \_dosamples #4:{} + \_ifexistfam + \_nobreak\_medskip \_dosamples #4:{}\_par \_ifx\_mathfaminfo\_empty \_else \_istoksempty\_catalogmathsample - \_iftrue {\_ttfixed \$Default math font\$: \_mathfaminfo \_par} + \_iftrue {\_nobreak \_ttfixed \$Default math font\$: \_mathfaminfo \_par} \_else Default math font (\_mathfaminfo): \_the\_catalogmathsample \_par \_fi\_fi \_else {\_qquad\_ttfixed ... family skipped, fonts not found in your system.\_nl @@ -60,14 +63,15 @@ } \_def\_dosamplesB#1{% \_ifx\_relax#1 \_else + \_ifhmode \_nl \_fi {\_ttfixed \_detokenize\_ea{\_usemodifiers}\_detokenize{#1}\_unskip:} {\_usemodifiers #1\_ea\_ifx\_the\_font \_nullfont \_ttfixed ... This font isn't available in your system.% - \_else \_the\_catalogsample \_fi }\_par + \_else \_the\_catalogsample \_fi }% \_ea \_dosamplesB \_fi } -\_def\_wlog#1{\_nobreak\_smallskip +\_def\_wlog#1{\_smallskip \_hbox to\_hsize{\_hskip25pt \_edef\_tmp{#1}\_replstring\_tmp{^^J}{\_endgraf}% \_smalltt \_noindent \_ea \string \_csname \_currfamily\_endcsname @@ -88,6 +92,8 @@ \_endgroup +\_the\_catalognextfam {} + \parindent=0pt \nonum\sec Customization of the catalog @@ -128,6 +134,11 @@ printed but families listed in the \code{\\catalogexclude} are excluded. For exa The \code{\\cataogexclude} is empty by default. +\bigskip The material printed at the beginning of each font family is stored in the +\code{\\catalognextfam} tokens register. Default value is \code{\\bigskip} but you can +set (for example) \code{\\catalognextfam={\\vfil\\break}} in order to start +each font family on a next page. + \bigskip The font families printed in the catalogue must be declared by the \code{\\_faminfo} command in the file \code{fams-ini.opm} (declarations used as default for \OpTeX/) or in the file \code{fams-local.opm}. The second file @@ -136,6 +147,8 @@ described in the \code{fams-ini.opm} file. \_endcode % ------------------------------------- +2023-06-04 line breaking optimized +2023-06-01 \_catalognextfam introduced, \_nobreak inserted 2023-03-09 \_famsrc introduced 2022-07-11 \_raggedbottom added 2022-02-22 \_ttfixed, \footline set as global, bug fixed diff --git a/macros/optex/base/fonts-resize.opm b/macros/optex/base/fonts-resize.opm index 4fc8ab1e28..323e1d72a0 100644 --- a/macros/optex/base/fonts-resize.opm +++ b/macros/optex/base/fonts-resize.opm @@ -167,7 +167,7 @@ You can declare a new {\em font switch} by `\font` primitive: \begtt \catcode`\<=13 \font \<font switch> = <font file name> <size spec> % for example: -\font \tipa = tipa10 at12pt % the font tipa10 at 10pt is loaded +\font \tipa = tipa10 at12pt % the font tipa10 at 12pt is loaded % usage: {\tipa TEXT} % the TEXT is printed in the loaded font. \endtt diff --git a/macros/optex/base/fonts-select.opm b/macros/optex/base/fonts-select.opm index cd70dab03c..d403a490d5 100644 --- a/macros/optex/base/fonts-select.opm +++ b/macros/optex/base/fonts-select.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \fontfam {Fonts selection system <2023-04-22>} % preloaded in format +\_codedecl \fontfam {Fonts selection system <2023-06-16>} % preloaded in format \_doc ----------------------------- The main principle of the Font Selection System is: run one or more @@ -131,7 +131,7 @@ \_unless\_ifcsname _f:\_csstring#2:main.fam\_endcsname \_isfont{#7}\_iffalse \_opwarning{Family [#1] skipped, font "#7" not found}\_endinput - \_lowercase{\_ifcsname _fams:#1\_endcsname}\_famsubstitute \_fi + \_ifcsname _fams:\_famfile\_endcsname \_famsubstitute \_fi \_else \_edef\_currfamily {\_csstring #2}\_def\_mathfaminfo{#6}% \_wterm {FONT: [#1] -- \_string#2 \_detokenize{(#3)^^J mods:{#4} vars:{#5} math:{#6}}}% @@ -311,12 +311,12 @@ \_protected\_def \_fontfam [#1]{% \_lowercase{\_edef\_famname{\_ea\_removespaces \_expanded{#1} {} }}% - \_isfile {f-\_famname.opm}\_iftrue \_opinput {f-\_famname.opm}% + \_isfile {f-\_famname.opm}\_iftrue \_edef\_famfile{f-\_famname}\_opinput {f-\_famname.opm}% \_else \_tryloadfamslocal \_edef\_famfile{\_trycs{_famf:\_famname}{}}% \_ifx\_famfile\_empty - \_ifcsname _fams:\_famname \_endcsname \_famsubstitute + \_ifcsname _fams:f-\_famname \_endcsname \_edef\_famfile{f-\_famname}\_famsubstitute \_else \_listfamnames \_fi \_else \_opinput {\_famfile.opm}% @@ -352,17 +352,19 @@ family installed. \`\_famsubstitute` is internal macro used in \^`\fontfam` and \^`\_famdecl` macros. It consumes the rest of the macro, runs \^`\nospacefuturelet` in order to - do `\endpinput` to the current `f-file` and runs \^`\fontfam` again. - The table of such substutitions are saved in the macros `\_fams:<family>`. + do `\endinput` to the current `f-file` and runs \^`\fontfam` again. + The table of such substutitions are saved in the macros `\_fams:<family-file>`. \_cod ----------------------------- -\_def \_fontfamsub [#1]#2[#3]{\_lowercase{\_sxdef{_fams:#1}{#3}}} - +\_def \_fontfamsub [#1]#2[#3]{\_tryloadfamslocal + \_lowercase{\_edef\_tmp{\_removespaces #1 {} }}% + \_sxdef{_fams:\_trycs{_famf:\_tmp}{f-\_tmp}}{#3}% +} \_def\_famsubstitute #1\_empty\_fi{\_fi\_fi\_fi - \_wterm {FONT: Family [\_famname] not found, substituted by [\_cs{_fams:\_famname}]}% + \_wterm {FONT-SUB: \_famfile\_space -> [\_cs{_fams:\_famfile}]}% \_nospacefuturelet\_tmp\_famsubstituteA % we want to \endinput current f-file } -\_def\_famsubstituteA{\_fontfam[\_cs{_fams:\_famname}]} +\_def\_famsubstituteA{\_fontfam[\_cs{_fams:\_famfile}]} \_public \fontfamsub ; @@ -413,17 +415,19 @@ pairs. The user can declare different samples and different behavior of the catalog, see the end of catalog listing for more information. The default parameters - \`\catalogsample`, \`\catalogmathsample`, \`\catalogonly` and - \`\catalogexclude` of the catalog are declared here. + \`\catalogsample`, \`\catalogmathsample`, \`\catalogonly`, + \`\catalogexclude` and \`\catalognextfam` of the catalog are declared here. \_cod ----------------------------- \_newtoks \_catalogsample \_newtoks \_catalogmathsample \_newtoks \_catalogonly \_newtoks \_catalogexclude +\_newtoks \_catalognextfam \_catalogsample={ABCDabcd Qsty fi fl áéíóúüů řžč ÁÉÍÓÚ ŘŽČ 0123456789} +\_catalognextfam={\_bigskip} -\_public \catalogonly \catalogexclude \catalogsample \catalogmathsample ; +\_public \catalogonly \catalogexclude \catalogsample \catalogmathsample \catalognextfam ; \_doc ----------------------------- The font features are managed in the \`\_fontfeatures` macro. @@ -587,6 +591,12 @@ described in the section~\ref[fontfamfiles]. Font modifiers and variant selectors may be declared here. The loaded family is set as current and `\rm` variant selector is processed. +When \^`\fontfam` `[<Font Family>]` is used and the given +family isn't found in the current \TeX/ system and +the <Font Family> is previously declared by +\^`\fontfamsub``[<Font Family>][<Other Family>]` +then \OpTeX/ does the given substitution and runs \^`\fontfam``[<Other Family>]`. + The available declared font modifiers and declared variant selectors are listed in the log file when the font family is load. Or you can print `\fontfam[catalog]` to show available font modifiers and variant selectors. @@ -935,6 +945,8 @@ with Unicode fonts loaded by \^`\fontfam`. \endinput +2023-06-16 \fontfamsub improved. +2023-05-30 \catalognextfam introduced. 2023-04-22 \setwordspace: \fontdimens reset, bug fixed. 2023-03-09 \_famsrc, \fontfamsub introduced 2022-12-01 \faminfo saves f-<filename> to the format only when needed diff --git a/macros/optex/base/hisyntax-python.opm b/macros/optex/base/hisyntax-python.opm index 12f7ebeeb4..b38fd9477a 100644 --- a/macros/optex/base/hisyntax-python.opm +++ b/macros/optex/base/hisyntax-python.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \_hisyntaxpython {Syntax highlighting for Python sources <2020-04-04>} +\_codedecl \_hisyntaxpython {Syntax highlighting for Python sources <2023-10-25>} \_newtoks \_hisyntaxpython \_newtoks \_hicolorspython @@ -57,7 +57,7 @@ \_replthis{E\e\o+\c}{E+}\_replthis{E\e\o-\c}{E-} \_replthis{\e j}{j\e} % - \_replfromto{\n\o@\n}{^^J}{\z R{#1}^^J} % decorators + \_replfromto{\b\n\n\o@\n}{^^J}{\z K{@}\z R{#1}^^J} % decorators % \_def\o#1{\z O{#1}} \_def\c#1\e{\z N{#1}} @@ -80,3 +80,5 @@ This code was greatly inspired by the OPMac hisyntax macros for Python: created by Petr Krajnik. +2023-10-25 decorators: hi-syntax corrected +2020-04-04 released diff --git a/macros/optex/base/if-macros.opm b/macros/optex/base/if-macros.opm index 148c855941..415b2c01c8 100644 --- a/macros/optex/base/if-macros.opm +++ b/macros/optex/base/if-macros.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \newif {Special if-macros, is-macros and loops <2023-01-16>} % preloaded in format +\_codedecl \newif {Special if-macros, is-macros and loops <2023-10-17>} % preloaded in format \_doc ---------------------------- \secc Classical \code{\\newif} @@ -336,6 +336,20 @@ \_public \casesof ; \_doc ----------------------------- + \`\qcasesof` `{<string>} <list of cases>` behaves like \^`\casesof` but it + compares phrases with the given <string> using \^`\isequal`. + The <list of cases> includes pairs + `{<phrase>} {<what to do if string=phrase>}` finalized by a + pair `\_finc {<what to do else>}`. + \_cod ----------------------------- + +\_long\_def \_qcasesof #1#2#3{\_ifx\_finc#2\_ea\_ignoresecond \_else \_ea\_usesecond \_fi + {#3}{\_isequal{#1}{#2}\_iftrue \_ea\_ignoresecond \_else \_ea\_usesecond \_fi + {\_finc{#3}}{\_qcasesof{#1}}}% +} +\_public \qcasesof ; + + \_doc ----------------------------- \`\xcasesof` `<list of pairs>` extends the features of the macro \^`\casesof`. Each pair from the `<list of pairs>` is in the format `{<if statement>}{<what to do>}`, only the last pair must have the different @@ -346,22 +360,23 @@ \begtt \message {The \tmpnum has \xcasesof {\ifnum\tmpnum>0 } {positive} - {\ifnum\tmpnum=0 } {equal to zero} - \_finc {negative} value} + {\ifnum\tmpnum=0 } {zero} + \_finc {negative} value} \endtt The \^`\xcasesof` macro works with principle: first true condition wins, next conditions are not evaluated. \_cod ----------------------------- -\_long\_def \_xcasesof #1{\_xcasesofA #1\_finc} -\_long\_def \_xcasesofA #1#2\_finc #3{% - \_ifx #1\_finc \_ea\_ignoresecond\_else \_ea\_usesecond\_fi - {#3}{#1#2\_ea\_ignoresecond\_else \_ea\_usesecond\_fi {\_finc{#3}}{\_xcasesof}}% +\_def \_xcasesof {\_nospacefuturelet\_next\_xcasesofA} +\_def \_xcasesofA {\_ifx\_next\_finc \_ea\_usesecond \_else \_ea \_xcasesofB \_fi} +\_long\_def \_xcasesofB #1#2{% + #1\_ea\_ignoresecond\_else \_ea\_usesecond\_fi {\_finc{#2}}{\_xcasesof}% } \_public \xcasesof ; \_endcode +2023-10-17 \qcasesof introduced, \xcasesof reimplemented. 2023-01-16 \isnextchar created expandable. 2022-12-02 \xcasesof: its first parameter is \long too. 2022-11-29 renamed to \casesof, \xcasesof. diff --git a/macros/optex/base/keyval.opm b/macros/optex/base/keyval.opm index 11a8663b16..68f3fea536 100644 --- a/macros/optex/base/keyval.opm +++ b/macros/optex/base/keyval.opm @@ -1,12 +1,12 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \readkv {Key-value dictionaries <2023-03-11>} % preloaded in format +\_codedecl \readkv {Key-value dictionaries <2023-10-23>} % preloaded in format \_doc ---------------------------- {\bf Implementation.}\nl The \`\readkv``<list>` expands its parameter and does replace-strings in order to - remove spaces around equal signs and after commas. - Then \`\_kvscan` reads the parameters list finished by `,\_fin,` + remove spaces around equal signs and commas. + Then \`\_kvscan` reads the parameters list finished by `,\_fin` and saves values to `\_kv:<dict>:<key>` macros. The `\_kvx:<dict>:<key>` is processed (if it is defined) with parameter <value> after it.\nl @@ -18,11 +18,11 @@ if the `<key>` is defined in current <dict>. \_cod ---------------------------- -\_def\_readkv#1{\_ea\_def\_ea\_tmpb\_ea{#1}% - \_replstring\_tmpb{= }{=}\_replstring\_tmpb{ =}{=}\_replstring\_tmpb{, }{,}% - \_ea \_kvscan\_tmpb,\_fin,} -\_def\_kvscan#1,{\_ifx\_fin#1\_empty\_ea\_ignoreit \_else\_ea\_useit \_fi - {\_kvsd #1==\_fin \_kvscan}} +\_def\_readkv#1{\_ea\_def\_ea\_tmpb\_ea{#1,}% + \_replstring\_tmpb{= }{=}\_replstring\_tmpb{ =}{=}\_replstring\_tmpb{ ,}{,}% + \_ea \_nospaceafter \_ea\_kvscan\_tmpb\_fin} +\_def\_kvscan#1,#2{\_ifx^#1^\_else \_kvsd #1==\_fin \_fi + \_ifx\_fin#2\_empty \_ea\_ignoreit \_else\_ea\_useit \_fi {\_kvscan#2}} \_def\_kvsd#1=#2=#3\_fin{\_sdef{\_kvcs#1}{#2}% \_trycs{_kvx:\_the\_kvdict:#1}% {\_trycs{_nokvx:\_the\_kvdict}{\_ea\_ignoreit}{#1}\_ea\_ignoreit}{#2}} @@ -88,7 +88,7 @@ user can set the `draft` option without the value. Then you can do \iskv{draft}\iftrue ...draft mode... \else ...final mode... \fi ...} \endtt -Maybe, you want to allow not ony `draft` option but `final` option (which is +Maybe, you want to allow not only `draft` option but `final` option (which is opposite to `draft`) too and you want to apply the result from the last given option. Then `\iskv` doesn't work because you can only check if both options are declared but you don't know what one is given as last. But you can @@ -110,7 +110,7 @@ then `\readkv{opt=HELLO}` prints \"opt is HELLO". The \^`\nokvx` `{<code>}` can declare a <code> processed for all <keys> undeclared by \^`\kvx`. The `#1` and `#2` can be used in the <code>, `#1` is <key>, `#2` is <value>. If `\nokvx` is unused then nothing is done -for undeclared <key>. Example: `\nokvx{\opwarnig{Unknown option "#1"}}`. +for undeclared <key>. Example: `\nokvx{\opwarning{Unknown option "#1"}}`. The default dictionary name (where key-value pairs are processed) is empty. You can use your specific dictionary by @@ -123,9 +123,12 @@ Package options can be processed when Recommendation: If the value of the key-value pair includes `=` or `,` or `]`, then use the syntax `<key>={<value>}`. -\_endinput +A more extensive example can be found in +\ulink[http://petr.olsak.net/optex/optex-tricks.html\#roundframe]{\OpTeX/ trick 0073}. +\_endinput +2023-10-23 minor changes in \readkv, empty key isn't processed. 2023-03-11 \nokvx: \fi bug (due to \afterfi in \trycs) fixed. 2023-01-13 \kvx parameter added, \nokvx introduced. 2023-01-07 \kvdict, \kvx, \iskv added. diff --git a/macros/optex/base/lang-data.opm b/macros/optex/base/lang-data.opm index 5b24c0999a..17aa26c4bf 100644 --- a/macros/optex/base/lang-data.opm +++ b/macros/optex/base/lang-data.opm @@ -162,10 +162,40 @@ \_monthw et jaanuar veebruar märts aprill mai juuni juuli august september oktoober november detsember \_sdef{_mt:today:et}{\_the\day.~\_mtext{m\_the\_month} \_the\_year} -\_quotationmarks{„“„“} +\_quotationmarks et {„“„“} + +\_langdata he {Hebrew} % ----------------------------------------------- +\_langw he פרק טבלה איור נושא +\_langb he {, ו- } { ועמיתים.} {\,מהדורה} {מצוטט מ-~} {כרך~} {מס׳~} {עמודים~} {עמ׳~} {:מחבר~} {:מחברים~} + {זמין מ- } {זמין גם מ- } + {עבודת גמר לתואר בוגר אוניברסיטה} {עבודת גמר לתואר מוסמך אוניברסיטה} {דיסרטציה} +\_monthw he ינואר פברואר מרץ אפריל מאי יוני + יולי אוגוסט ספטמבר אוקטובר נובמבר דצמבר +\_sdef{_mt:today:he}{{\_textdir TLT\_the\_day} ב\_mtext{m\_the\_month}, {\_textdir TLT\_the\_year}} +\_quotationmarks he {„”‚’} + +\_def \_sortingdatahe {% + /,{ },-,&,@,% + אﬡאּאָאַ,בבֿבּ,גגּ,דﬢדּ,הﬣהּ,ווּוֹ,זזּ,ח,טטּ,ייּיִ,% + כﬤכּכֿךךּ,לﬥלּ,ממּםﬦ,ננּן,ססּ,עﬠ,פפּפֿףףּ,% + צצּ,קקּ,ררּﬧ,ששּשׁשּׁשׂשּׂ,תתּﬨ,% + 0,1,2,3,4,5,6,7,8,9,'% +} +\_def \_ignoredcharshe {% +^^^^0591,^^^^0592,^^^^0593,^^^^0594,^^^^0595,^^^^0596,^^^^0597,^^^^0598,% +^^^^0599,^^^^059a,^^^^059b,^^^^059c,^^^^059d,^^^^059e,^^^^059f,% +^^^^05a0,^^^^05a1,^^^^05a2,^^^^05a3,^^^^05a4,^^^^05a5,^^^^05a6,^^^^05a7,% +^^^^05a8,^^^^05a9,^^^^05aa,^^^^05ab,^^^^05ac,^^^^05ad,^^^^05ae,^^^^05af,% +^^^^05b0,^^^^05b1,^^^^05b2,^^^^05b3,^^^^05b4,^^^^05b5,^^^^05b6,^^^^05b7,% +^^^^05b8,^^^^05b9,^^^^05ba,^^^^05bb,^^^^05bc,^^^^05bd,^^^^05be,^^^^05bf,% +^^^^05c0,^^^^05c1,^^^^05c2,^^^^05c3,^^^^05c4,^^^^05c5,^^^^05c6,^^^^05c7,% +^^^^05f3,^^^^05f4% +} +\_def \_compoundcharshe {} \_endcode +2023-08-30: Hebrew data added 2022-10-11: \postexhyphenchar setting added to cs and sk languages 2022-10-10: { ed.} changed to {\,ed.} 2022-08-31: \_sortingdatahu corrected diff --git a/macros/optex/base/lang-decl.opm b/macros/optex/base/lang-decl.opm index 753df5f82e..2d8d2cd017 100644 --- a/macros/optex/base/lang-decl.opm +++ b/macros/optex/base/lang-decl.opm @@ -157,7 +157,7 @@ example: \begtt \_preplangmore ru {\_frenchspacing \_setff{script=cyrl}\selectcyrlfont} - \_addto\_langdefaut {\_setff{}\selectlatnfont} + \_addto\_langdefault {\_setff{}\selectlatnfont} \endtt The macros `\selectcyrlfont` and `\selectlatnfont` are not defined in \OpTeX/. If you follow this example, you have to define them after your diff --git a/macros/optex/base/lists.opm b/macros/optex/base/lists.opm index e7785678dd..b372edf635 100644 --- a/macros/optex/base/lists.opm +++ b/macros/optex/base/lists.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \begitems {Lists: begitems, enditems <2022-02-25>} % preloaded in format +\_codedecl \begitems {Lists: begitems, enditems <2023-10-20>} % preloaded in format \_doc ----------------------------- \`\_aboveliskip` is used above the list of items,\nl @@ -71,11 +71,11 @@ The \`\style` `<letter>` does \`\_printitem``={\_item:<letter>}`. More exactly: \^`\begitems` does \^`\_printitem=`\^`\defaultitem` first, then \^`\style` `<letter>` does \^`\_printitem``={\_item:<letter>}` - when it is used and finally, `\_startitem` alias `*` uses \^`\_printitem`. + when it is used and finally, \^`\_startitem` alias `*` uses \^`\_printitem`. \_cod ----------------------------- \_def\_style#1{% - \_ifcsname _item:#1\_endcsname \_printitem=\ea{\_csname _item:#1\_endcsname}% + \_ifcsname _item:#1\_endcsname \_printitem=\_ea{\_csname _item:#1\_endcsname}% \_else \_printitem=\_defaultitem \_fi } \_sdef{_item:o}{\_raise.4ex\_hbox{$\_scriptscriptstyle\_bullet$} } @@ -88,6 +88,8 @@ \_sdef{_item:A}{\_uppercase\_ea{\_athe\_itemnum}) } \_sdef{_item:x}{\_raise.3ex\_fullrectangle{.6ex}\_kern.4em} \_sdef{_item:X}{\_raise.2ex\_fullrectangle{1ex}\_kern.5em} +\_sdef{_item:d}{\_aftergroup\_dword} +\_def\_dword#1#2{{\_bf #2 }\_ignorespaces} % #1 is \_ignorespaces from \_startitem \_doc ----------------------------- \`\_athe``{<num>}` returns the `<num>`s lowercase letter from the alphabet.\nl @@ -121,6 +123,7 @@ \_endcode % ------------------------------------- +2023-10-20 \style d moved from OpTeX trick 0108 to the format 2022-02-25 \olistskipamount, \ilistskipamount, \itemskipamount introduced 2021-03-10 \_ifmmode*\_else\_ea\_startitem\_fi added to * defintition 2020-04-21 \isnextchar\par added to \enditems diff --git a/macros/optex/base/makeindex.opm b/macros/optex/base/makeindex.opm index d939d9ea64..a3af094f26 100644 --- a/macros/optex/base/makeindex.opm +++ b/macros/optex/base/makeindex.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \makeindex {Makeindex and sorting <2023-03-12>} % preloaded in format +\_codedecl \makeindex {Makeindex and sorting <2023-06-02>} % preloaded in format \_doc ----------------------------- \^`\makeindex` implements sorting algorithm at \TeX/ macro-language level. @@ -203,11 +203,14 @@ The \`\_preparesorting` `\,<string>` converts `<string>` to `\_tmpb` with respect to the data initialized in \^`\_setprimarysorting` or \^`\_setsecondarysorting`.\nl - The compoud characters are converted by the \`\_docompound` macro. + The part of the string after `^^^` is ignored (you can have the same + sorting key for different things) and + the compoud characters are converted by the \`\_docompound` macro. \_cod ----------------------------- \_def \_preparesorting #1{% - \_edef \_tmpb {\_ea\_ignoreit\_csstring #1}% \,<string> -> <string> + \_edef \_tmpb {\_ea\_ignoreit\_csstring #1}% \,<string> -> <string> + \_edef\_tmpb{\_ea \_stripfromcaret \_tmpb ^^^\_fin}% <string>^^^<ignore> -> <string> \_ea \_docompound \_compoundchars \_relax:{} % replace compound characters \_lowercase \_ea{\_ea\_def \_ea\_tmpb \_ea{\_tmpb}}% convert in respect to \_sortingdata \_ea\_replstring \_ea\_tmpb \_ea{\_csstring\^^I}{}% remove ignored characters @@ -215,6 +218,7 @@ \_def \_docompound #1:#2 {% \_ifx\_relax#1\_else \_replstring\_tmpb {#1}{#2}\_ea\_docompound \_fi } +\_def\_stripfromcaret #1^^^#2\_fin{#1} \_doc ----------------------------- Macro \`\_isAleB` `\,<string1> \,<string2>` returns the result of comparison @@ -567,6 +571,7 @@ \_endcode % ------------------------------------- +2023-06-02 \_stripfromcaret introduced 2023-03-12 \_definefirstii introduced 2022-06-28 \_reversewords for French sorting introduced 2022-06-28 \_sortingdatalatin covers more languages diff --git a/macros/optex/base/math-macros.opm b/macros/optex/base/math-macros.opm index a132cb4176..00adc9f1aa 100644 --- a/macros/optex/base/math-macros.opm +++ b/macros/optex/base/math-macros.opm @@ -596,8 +596,8 @@ \_protected\_def\_cong{\_mathrel{\_mathpalette\_overeq\_sim}} % congruence sign \_def\_overeq#1#2{\_lower.05em\_vbox{\_lineskiplimit\_maxdimen\_lineskip=-.05em \_ialign{$\_math#1\_hfil##\_hfil$\_crcr#2\_crcr=\_crcr}}} -\_protected\_def\_notin{\_mathrel{\_mathpalette\_cancel\_in}} -\_def\_cancel#1#2{\_math\_ooalign{$\_hfil#1\_mkern1mu/\_hfil$\_crcr$#1#2$}} +\_protected\_def\_notin{\_mathrel{\_mathpalette\_icancel\_in}} +\_def\_icancel#1#2{\_math\_ooalign{$\_hfil#1\_mkern1mu/\_hfil$\_crcr$#1#2$}} \_protected\_def\_rightleftharpoons{\_mathrel{\_mathpalette\_rlhp{}}} \_def\_rlhp#1{\_vcenter{\_math\_hbox{\_ooalign{\_raise.2em \_hbox{$#1\_rightharpoonup$}\_crcr diff --git a/macros/optex/base/math-preload.opm b/macros/optex/base/math-preload.opm index a3ac3e44b3..fbfdc8af1e 100644 --- a/macros/optex/base/math-preload.opm +++ b/macros/optex/base/math-preload.opm @@ -138,7 +138,7 @@ \`\_mfactor` sets scaling factor for given math fonts family related to text font size. It does the setting `\_ptmunit=<factor>\_ptunit` where the <factor> is defined by `\sdef{_mfactor:<family>}{<factor>}`. - For eample, you can set `\sdef{_mfactor:1}{0.95}` if you found that + For example, you can set `\sdef{_mfactor:1}{0.95}` if you found that this scaling of math family 1 gives better visual compatibility with used text fonts. If not declared then scaling factor is~1. \_cod ----------------------------- diff --git a/macros/optex/base/optex-tricks.opm b/macros/optex/base/optex-tricks.opm new file mode 100644 index 0000000000..89fc7dd5e7 --- /dev/null +++ b/macros/optex/base/optex-tricks.opm @@ -0,0 +1,756 @@ +%% This is part of the OpTeX project, see http://petr.olsak.net/optex + +\_codedecl \_undefined {OpTeX tricks ready to autoload <2023-11-15>} % chunks loaded on demand + +% Selected OpTeX tricks are here, they are auto-loaded if the macro is used first +% namespace: optextrick + +\_trick 0057 \begfile \createfile ; +%%%%%%%%%%%% + +\newwrite\.outfile +\def\begfile #1 {\_immediate\_openout\.outfile={#1}% + \_begingroup \_setverb \_endlinechar=`\^^J \.begfileA^^J% +} +\_ea\_def\_ea\.begfileA\_ea#\_ea1\_ea^^J\_csstring\\endfile#2^^J{\_endgroup + \_ifx^#1^\_else \_immediate\_write\.outfile{\_ignoreit #1}\_fi + \_immediate\_closeout\.outfile +} +\_let\createfile=\begfile + +\_trick 0054 \beglua \begLUA \logginglua ; +%%%%%%%%%%%% + +\_newtoks\.luamacros +\.luamacros={\_let\\=\_nbb \_edef\%{\_csstring\%}\_edef\#{\csstring\#}\_let\n=\_relax} +\_def\beglua{\.savelineno\_bgroup \_setverb \_endlinechar=`\^^J \.begluaA} +\_ea\_def\_ea\.begluaA\_ea#\_ea1\_csstring\\endlua^^J{\_egroup\.debuglua{#1}\_directlua{#1}} +\_def\begLUA{\.savelineno\_bgroup \_setverb \_endlinechar=`\^^J \_catcode`\\=0 \.begLUAA} +\_def\.begLUAA#1\endLUA^^J{\_the\.luamacros\.debuglua{#1}\_directlua{#1}\_egroup} +\_def\.savelineno{\_edef\.tmp{\_the\_numexpr\_inputlineno+1}} +\_let\.debuglua=\_ignoreit +\_def\.printloglua#1{\_wlog{lua code processed (l.\.tmp):^^J#1-------------}} +\_def\logginglua{\_let\.debuglua=\.printloglua} + +\_trick 0055 \sethours \setminutes \setseconds \setweekday ; +%%%%%%%%%%%% + +\_newcount\.hours \_newcount\.minutes \_newcount\.seconds \_newcount\.weekday + +\_def\setminutes{% + \.minutes=\_directlua{tex.sprint(\_the\_time\_pcent 60)}\_relax + \.hours=\_directlua{tex.sprint(math.floor(\_the\_time/60))}\_relax +} +\_let\sethours=\setminutes +\_def\setseconds{\_ea\.setsecondsA\_pdffeedback creationdate\_relax} +\_def\.setsecondsA#1#2#3#4#5#6#7#8#9{\.setsecondsB} +\_def\.setsecondsB#1#2#3#4#5#6#7#8\_relax{\.seconds=#6#7\_relax} +\_def\setweekday{\.weekday=\_directlua{% Zeller's algorithm: + local m, y, K, J + m = \_the\_month \_ifnum\_month<3 +12 \_fi + y = \_the\_year \_ifnum\_month<3 -1 \_fi + K = y \_pcent 100 + J = math.floor(y/100) + tex.sprint((\_the\_day + math.floor((13*(m+1))/5) + K + + math.floor(K/4) + math.floor(J/4) - 2*J + 6)\_pcent 7) + }\_relax +} +\_def\.Othe#1{\_ifnum#1<10 0\_fi\_the#1} + +\_nspublic \hours \minutes \seconds \weekday \Othe ; + +\_trick 0063 \showpglists ; +%%%%%%%%%%%% + +\_def\.addshowpglists{\_directlua{ + local nodetree = require("nodetree") + callback.add_to_callback("pre_shipout_filter", function(head) + nodetree.print(head) + return head + end, "showpglists") }} +\_gdef\.removeshowpglists{\_directlua{ + callback.remove_from_callback("pre_shipout_filter", "showpglists") }} + +\_def\showpglists #1 {\_addto\.showpgs{#1,}} +\_def\.showpgs{,} + +\_addto\_begoutput{% + \_ea\_isinlist\_ea\.showpgs\_ea{\_ea,\_the\_pageno,}\_iftrue + \.addshowpglists + \_addto\_endoutput{\.removeshowpglists}% + \_fi +} + +\_trick 0101 \runsystem ; +%%%%%%%%%%%% + +\_newcount\.exitstatus +\_def\runsystem#1{\.exitstatus=\_directlua{ + texio.write_nl("") + local status = os.execute("\_luaescapestring{#1}") + texio.write("log", "\_nbb runsystem{\_luaescapestring{#1}} status: " .. (status or -1) .. "\_string\n") + tex.print(status or -1) +} } + +\_nspublic \exitstatus ; + +\_trick 105 \directoutput ; +%%%%%%%%%%% + +\_def\directoutput{\_begingroup \_afterassignment\.directoutputA \_setbox0=} +\_def\.directoutputA{\_aftergroup \.directoutputB} +\_def\.directoutputB{\_preshipout0\_box0 + \_pdfpageheight=\_dimexpr\_ht0+\_dp0+2\_vvkern \_relax + \_pdfpagewidth=\_dimexpr\_wd0+2\_hhkern\_relax + \_hoffset=\_hhkern \_voffset=\_vvkern + \_shipout\_box0 + \_incr\_pageno + \_endgroup +} + +\_trick 0078 \algol ; +%%%%%%%%%%%% + +\_newtoks \_hisyntaxalg +\_hisyntaxalg = { + \_hicolor K \_bf % Keywords + \_foreach {Require:}{Ensure:}{Input:} + {while}{do}{if}{then}{else}{end}{function}{return}{print} + {for}{all}{range}{continue}{repeat}{until}{loop} + {not}{and}{or}{xor}{true}{false} + \_do {\_replthis{\n#1\n}{\z K{#1}}} +} +\_def\.algolmath#1${\_catcodetable\_optexcatcodes \_scantextokens{#1}$} + +\_def\algol{\_catcode`$=3 % + \_everymath={\.algolmath}% + \_def\_ttfont{\_rm}% + \_catcode`\!=13 + \_bgroup \_lccode`\~=`\! \_lowercase{\_egroup \_def~##1~{\_ifx^##1^!\_else{\_bf##1}\_fi}}% + \_hisyntax{ALG}% +} +\_def\var#1{{\_it\_adef _{\_vrule height.4pt width4pt\_relax}#1}} + +\_trick 0079 \ttlineref ; +%%%%%%%%%%%% + +\_def\ttlineref#1{\_adef#1[##1]{\.setlref{##1}}} +\_protected\_def\.setlref#1{\_sxdef{ttlin:#1}{\_the\_ttline}} +\_def\lref[#1]{\_trycs{ttlin:#1}{??}} + +\_trick 0011 \scaleto \scaletof ; +%%%%%%%%%%%% + +\_def\scaleto#1#{\_def\.tmp{#1}\.scaletoA} +\_def\.scaletoA#1{\_setbox0=\_hbox{{#1}}% + \_edef\.tmp{\_expr{\_bp{\.tmp}/\_bp{\_wd0}}}% + \_transformbox{\_pdfscale{\.tmp}{\.tmp}}{#1}} + +\_def\scaletof#1#{\_def\.tmp{#1}\.scaletofA} +\_def\.scaletofA#1{\_setbox0=\_hbox{{#1}}% + \_edef\.tmpa{\_expr{\_bp{\.tmp}/\_bp{\_wd0}}}% + \.scaletoA{\_setfontsize{mag\.tmpa}\_currvar#1}} + +\_trick 0053 \ignoreinspic ; +%%%%%%%%%%%% + +\_def\.trydef #1{\_ifx#1\_undefined \_afterfi{\_def#1}\_else \_afterfi{\_def\.tmp}\_fi} +\.trydef\nopicw{5cm} +\.trydef\nopicratio{1.7} + +\_let\.inspicBori=\_inspicB +\_def\.inspicBnew#1{% + \_isfile{\_the\_picdir#1}\_iftrue + \_edef\.filename{\_the\_picdir#1}% + \_setbox0=\_hbox\_bgroup\.inspicBori{#1}% \egroup is in \inspicBori + \_else + \_edef\.filename{NONE: \_the\_picdir#1}% + \_ifdim\_picheight=0pt \_picheight=\_expr{1/\nopicratio}\_picwidth \_fi + \_ifdim\_picwidth=0pt \_picwidth=\nopicratio\_picheight \_fi + \_ifdim\_picwidth=0pt \_picwidth=\nopicw\_relax \_picheight=\_expr{1/\nopicratio}\_picwidth \_fi + \_setbox0=\_hbox to\_picwidth{\_vbox to\_picheight{}\_hss}% + \_fi + {\LightGrey \_vrule height\_ht0 width\_wd0\Black\_raise1ex\_llap{\.filename\ }}\_egroup +} +\_def\ignoreinspic{\_let\_inspicB=\.inspicBnew} + +\_trick 0047 \style m \keepstyle ; +%%%%%%%%%%%% + +\_def\.iprefix#1{} +\_addto\_setlistskip{\_ifnum\_ilevel>1 \_edef\.iprefix{\.iprefix.\_the\_itemnum}\_fi} +\_sdef{_item:m}{\.iprefix.\_the\_itemnum. } +\_def\keepstyle{\_defaultitem=\_printitem} + +\_trick 0048 \easylist ; +%%%%%%%%%%%% + +\_def\easylist{\_adef*{\.countlist}\_def\enditems{\_fornum 1..\_ilevel\_do{\_enditems}}} +\_def\.aast{\.countlist} +\_def\.countlist{\_tmpnum=1 \.countlistA} +\_def\.countlistA{\_futurelet\.next\.countlistB} +\_def\.countlistB{\_ifx\.next\.aast \_ea\.countlistC\_else \_ea\.countlistD \_fi} +\_def\.countlistC#1{\_incr\_tmpnum \.countlistA} +\_def\.countlistD{% + \_ifnum\_tmpnum>\_ilevel \_fornum \_ilevel..\_tmpnum-1 \_do{\_begitems\easylist}\_else + \_ifnum\_tmpnum<\_ilevel \_fornum \_tmpnum..\_ilevel-1 \_do{\_enditems}\_fi\_fi + \_startitem} + +\_trick 0092 \fcread ; +%%%%%%%%%%%% + +\_newtoks\.fcithook +\_def\.fcitlist{} + +\_def\.xbibadd#1{% + \_unless \_ifcsname fcit:\_entrykey\_endcsname + \_sxdef{fcit:\_entrykey}{}\_xdef\.fcitlist{\.fcitlist\fcititem[\_entrykey]}\_fi + \_global \_ea\_addto\_csname fcit:\_entrykey\_ea\_endcsname\_ea{\_expanded{#1}}% +} +\_def\.ubibfield{\_unexpanded\_ea{\_bibfield}} +\_def\.remdotspace #1. \_end #2\_relax #3{% + \_ifx ^#2^\_else \_ea \_gdef \_csname fcit:#3\_endcsname{#1}\_fi} +\_def\.remdotxspace #1.\ \_end #2\_relax #3{% + \_ifx ^#2^\_else \_ea \_gdef \_csname fcit:#3\_endcsname{#1}\_fi} + +\.fcithook{ + \_def\_dofullfield#1#2{\_def\_dofield##1{#1}\.xbibadd{\_ea\_dofield\_ea{\.ubibfield}}} + \_def\_dofemptyfield#1#2{\_def\_dofield##1{#2}\.xbibadd{\_ea\_dofield\_ea{\.ubibfield}}} + \_def\_bprintaB #1*#2*#3\_fin{% + \_ifx\_bibfield\.readauthor \_def\_bibfield{}\.readauthor \_fi + \_ifx\_bibfield\.readeditor \_def\_bibfield{}\.readeditor \_fi + \.xbibadd{\_if^#3^#1\_else\_ea\_bprintaC\_ea{\.ubibfield}{#1}{#2}\_fi}} + \_def\_authorini#1\_endcsname{\_edef\_bibfield{\.ubibfield\_authorname}} + \_def\_editorini#1\_endcsname{\_edef\_bibfield{\.ubibfield\_editorname}} + \_def\_addauthlist{} + \_def\_bprintv [#1]#2#3{#3} + \_def\_Inclause{\.xbibadd{In:~}} + \_def\_dobibmark{} + \_let\_url=\_relax \_let\_ulink=\_relax \_def\_preurl{} + \_def\_citelist{\_citeI[*]} + \_let\fcititem=\_relax +} +\_def\.readauthor{\_loopauthors {author}} +\_def\.readeditor{\_loopauthors {editor}} + +\_def\fcread (#1) #2 {{% + \_setbox0=\_vbox{\_bibtexhook=\.fcithook + \_bibpart{fullcites}\_nocite[*]\_usebib/c (#1) #2 } + \_def\fcititem[##1]{% + \_ea\_ea\_ea \.remdotspace \_csname fcit:##1\_endcsname \_end . \_end \_relax {##1}% + \_ea\_ea\_ea \.remdotxspace \_csname fcit:##1\_endcsname \_end .\ \_end \_relax {##1}% + }\.fcitlist % removing last .\space or .space from each bib-record +}} +\_def\fullcite[#1]{\_trycs{fcit:#1}{??\_opwarning{\_string\fullcite[#1] unknown label}}} + +\_trick 0071 \shadedframe ; +%%%%%%%%%%%% + +\_def\.shadedframedefaults {% defaults: + frame-color=\Grey, % color of frame rules + text-color=\Black, % color ot text inside the frame + shadow-color=\LightGrey, % color of shadow + bg-color=\Yellow, % background color inside the frame + rule-width=1pt, % width of rules used in the frame + v-margins=4pt, % vertical space between text and frame + h-margins=4pt, % horizontal space between text and frame + shade-width=4pt, % the width of the shadow + text-width=4cm, % width of the text inside the frame +} +\_optdef\shadedframe [] #1{\_bgroup + \_readkv\.shadedframedefaults \_readkv{\_the\_opt}% + \_vvkern=\_kv{v-margins}\_hhkern=\_kv{h-margins}% + \_rulewidth=\_kv{rule-width}\_hsize=\_kv{text-width}\relax + \_kv{frame-color}% + \_setbox0=\_hbox{\_frame{\_vbox{\_kv{text-color}\_noindent\_ignorespaces#1}}}% + \_edef\.htzo{\_the\_ht0}\_edef\.wdzo{\_the\_wd0}% + \_kv{shadow-color}% + \_hbox{\_vbox{\_hbox{\_rlap{\_kv{bg-color}\_vrule height\_ht0 width\_wd0 depth\_dp0}\_box0}% + \_nointerlineskip \_moveright\_kv{shade-width} + \_hbox{\_vrule height\_kv{shade-width}width\.wdzo}\_kern-\_kv{shade-width}}% + \_kern-\_kv{shade-width}\_vrule height\.htzo width\kv{shade-width}}% + \_egroup +} + +\_trick 0073 \roundframe ; +%%%%%%%%%%%% + +\_def \.roundframedefaults {% default parameters: + round-corner=3mm, % diameter of corners + title-bgcolor=\Blue, % background color of the title area + title-color=\White, % color of title text + title-font=\_bf, % font of title text + title-above=2pt, % space above the first line of title + title-below=1pt, % space below the last line of title + midrule-color=\Yellow, % color of the rule between title and text area + midrule-width=2pt, % thickness of the rule between title and text area + text-bgcolor=\LightGrey, % background color of the text area + text-color=\Black, % color of normal text + text-font=\_rm, % font of normal text + text-width=6cm, % text paragraph width; frame width = text width + margins + text-margins=3mm, % left and right margins + text-above=3pt, % space above the first line of text + text-below=1pt, % space below the last line of text + shadow-width=2pt, % shadow thickness (if 0pt then no shadow printed) +} +\_optdef \roundframe [] #1#2{\_bgroup + \_kvdict{_optextrick:roundframe}% dictionary of used key-value parameters + \_readkv\.roundframedefaults \_readkv{\_the\_opt}% + \_roundness=\_kv{round-corner}\_relax + \_hsize=\_kv{text-width}\_relax + \_leftskip=\_kv{text-margins}\_relax \_rightskip=\_leftskip + \_setbox0=\_vbox{% + \.bgbox{\_kv{title-bgcolor}}{\_kern\_kv{title-above}% + \_noindent\_strut\_kv{title-color}\_kv{title-font}#1\.parstrut\_kern\_kv{title-below}} + \_kv{midrule-color}\_hrule height\_kv{midrule-width}% + \.bgbox{\_kv{text-bgcolor}}{\_kern\_kv{text-above}% + \_noindent\_strut\_kv{text-color}\_kv{text-font}#2\.parstrut\_kern\_kv{text-below}}} + \_setbox1=\_vbox to\_dimexpr\_ht0-2\_roundness{}\_wd1=\_dimexpr\_wd0-2\_roundness\_relax + \_hbox{\_unless\_ifdim\_kv{shadow-width}=0pt \.roundframeshadow \_fi + \_clipinoval .5\_wd0 .5\_ht0 \_wd0 \_ht0 {\_box0}}% + \_egroup +} +\_def\.bgbox#1#2{\_setbox0=\_vbox{#2}\_hbox{\_rlap{#1\_vrule height\_ht0 depth\_dp0 width\_wd0}\_box0}} +\_def\.parstrut{\_par\_kern-\_prevdepth\_kern\_dp\_strutbox} +\_def\.roundframeshadow{\_raise\_roundness\_rlap{\_edef\_shadowb{\_bp{\_kv{shadow-width}}}% + \_inoval[\_fcolor=\Grey \_roundness=\_kv{round-corner} \_shadow=Y \_lwidth=0pt]{\_box1}}} +\_edef\.tmp{\_the\_kvdict} +{\_kvdict{_optextrick:roundframe} \_ea\_foreach\.roundframedefaults \_do #1#2=#3,{\_global\_kvx{#1#2}{}} + \_global\_nokvx{\_opwarning{\_string\roundframe: Unknown option "#1"}}} +\_kvdict=\_ea{\.tmp} % restoring \_kvdict, because \globaldefs=1 + +\_trick 0103 \cancel ; +%%%%%%%%%%%% + +\_def\cancel#1#{\_isempty{#1}\_iftrue \_afterfi{\cancel/} + \_else + \_lowercase{\_casesof #1} + / {\_let\.cancline=\.drawFslash} + \\ {\_let\.cancline=\.drawBslash} + x {\_def\.cancline{\.drawBslash\.drawFslash}} + - {\_let\.cancline=\.drawHline} + \_finc {}% + \_ea\.cancelA + \_fi +} +\_def\.cancelA{\_ifmmode \_ea\.cancelM \_else \_ea\.cancelT \_fi} +\_def\.cancelT#1{\_setbox0=\_hbox{#1}\.cancelF} % text mode +\_def\.cancelM#1{\_mathstyles{\_setbox0=\_hbox{$\_currstyle#1$}\_cancelF}} % math mode +\_def\.cancelF{\_edef\.tmp{\.cancline}\_quitvmode\_box0 \_pdfliteral{q \_useit{\cancelparams} \.tmp S Q}} +\_def\.drawFslash{\_bp{-\_wd0} \_bp{-\_dp0} m 0 \_bp{\_ht0} l } % forward slash +\_def\.drawBslash{\_bp{-\_wd0} \_bp{\_ht0} m 0 \_bp{-\_dp0} l } % backward slash +\_def\.drawHline {\_bp{-\_wd0} \_bp{.5ex} m 0 \_bp{.5ex} l } % horizontal line +\_ifx\cancelparams\_undefined \_def\cancelparams{1 0 0 RG 1 J .6 w}\_fi % color RG linetype J linewidth w + +\_trick 0070 \keystroke ; +%%%%%%%%%%%% + +\_ifx\keysize\_undefined \_newdimen\keysize \keysize=1.3em \_fi +\_ifx\keystrokefont\_undefined \_def\keystrokefont{\_setfontsize{mag.77}\_cs{sans}\_rm} \_fi + +\_newbox\.keylbox \_newbox\.keymbox \_newbox\.keyrbox +\_edef\.picheight{\_the\_picheight} +\_setbox\.keylbox=\_hbox{\_picheight=\keysize \_inspic{keystroke_left.pdf}} +\_setbox\.keymbox=\_hbox{\_picheight=\keysize \_inspic{keystroke_middle.pdf}} +\_setbox\.keyrbox=\_hbox{\_picheight=\keysize \_inspic{keystroke_right.pdf}} +\_picheight=\.picheight + +\_def\keystroke#1{\_setbox0=\_hbox{\keystrokefont#1}% + \_leavevmode \_lower.2\keysize \_hbox{\_copy\.keylbox + \_tmpdim=\_wd\.keymbox + \_ifdim\_wd0>\_tmpdim \_tmpdim=\_wd0 \_fi + \_ifdim\_tmpdim>\_wd\.keymbox + \_pdfsave \_pdfscale{\_expr{\_bp{\_tmpdim}/\_bp{\_wd\.keymbox}}}{1}% + \_rlap{\_copy\.keymbox}\_pdfrestore + \_else \_rlap{\_copy\.keymbox}\_fi + \_raise.33\keysize \_hbox to\_tmpdim{\_hss\_box0\_hss}\_copy\.keyrbox}% +} + +\_trick 0004 \colortab ; +%%%%%%%%%%%% + +\_def\.tabdC{\_futurelet\.next\.setcellcolor##\_fin\_hfil\_hfil} +\_def\.tabdL{\_futurelet\.next\.setcellcolor##\_fin\_relax\_hfil} +\_def\.tabdR{\_futurelet\.next\.setcellcolor##\_fin\_hfil\_relax} +\_def\.tabdP#1{\_futurelet\.next\.setcellcolor##\_fin\_vtop + {\_hsize=#1\_relax \_baselineskip=\_normalbaselineskip + \_lineskiplimit=0pt \_noindent\.tmp\_unsskip\_lower\_dp\_tstrutbox\_hbox{}}} +\_def\colortab{\_tablinespace=0pt \_let\_paramtabdeclarep=\.tabdP + \_let\_tabdeclarec=\.tabdC \_let\_tabdeclarel=\.tabdL \_let\_tabdeclarer=\.tabdR} +\_def\.setcellcolor{% + \_ifx\.next\_setcolor \_ea\.setcellcolorC\_else \_ea\.setcellcolorD\_fi} +\_def\.setcellcolorC\_setcolor#1#2#3#4\_fin#5#6{% + \_ifx#5\_vtop \_def\.tmp{#4}% + \_setbox0=\_hbox{\_the\_tabiteml\_vtop{\_localcolor#6}\_the\_tabitemr}% + \_the\_tabstrut {\_localcolor\_setcolor{#1}{#2}{#3}\_vrule width\_wd0}\_kern-\_wd0 \_box0 + \_else + \_setbox0=\_hbox{\_the\_tabiteml\_localcolor#4\_unsskip\_the\_tabitemr}% + {\_localcolor\_setcolor{#1}{#2}{#3}% + \_the\_tabstrut\_leaders\_vrule\_hskip\_wd0 \_ifx#5\_hfil plus1fil\_fi}\_kern-\_wd0 \_box0 + \_ifx#6\_hfil + {\_kern-.3bp \_localcolor\_setcolor{#1}{#2}{#3}\_leaders\_vrule\_hskip.3bp plus1fil}\_fi + \_fi +} +\_def\.setcellcolorD{\_ifx\cellcolor\undefined \_let\.next=\.setcellcolorN + \_else \_def\.next{\_ea\_ea\_ea\.setcellcolorC\cellcolor}% + \_fi \.next +} +\_def\.setcellcolorN#1\_fin#2#3{#2\_the\_tabiteml{\_localcolor#1\_unskip}\_the\_tabitemr#3} + +\_def\multispanc#1#2#3{\_multispan{#1}% + \_ea\_ea\_ea\.cellcolexp#2#3\_fin\_hfil\_hfil\_ignorespaces} +\_def\.cellcolexp{\_futurelet\.next\.setcellcolor} + +\_trick 0005 \crx ; +%%%%%%%%%%%% + +\_newcount\.tabline \.tabline=1 +\_def\crx {\_crcr \_ifodd\.tabline \.colortabline \_else\_noalign{\_hrule height0pt}\_fi \_incr\.tabline} +\_def\.colortabline{\_noalign{\_localcolor\LightGrey + \_hrule height\ht\_strutbox depth\_dimexpr\_dp\_strutbox +2\_tablinespace\_relax + \_kern-\_dimexpr\ht\_strutbox+\_dp\_strutbox +2\_tablinespace}} + +\_trick 0007 \crtop \crbot \crmid ; +%%%%%%%%%%%% + +\_def\crtop{\_crcr \_noalign{\_hrule height.6pt \_kern2.5pt}} +\_def\crbot{\_crcr \_noalign{\_kern2.5pt\_hrule height.6pt}} +\_def\crmid{\_crcr \_noalign{\_kern1pt\_hrule height.4pt\_kern1pt}} + +\_trick 0016 \longtable ; +%%%%%%%%%%%% + +\_def\longtable#1#2{\_goodbreak \_bgroup \_tablinespace=0pt \_let\_zerotabrule=\_empty + \_setbox0=\_table{#1}{\.strutT\_relax #2} + \_setbox1=\_vbox{\_unvbox0 \_setbox2=\_vbox{}\.revertbox} + \_setbox2=\_vbox{\_unvbox2 \_global\_setbox4=\_lastbox\_unskip \_global\_setbox5=\_lastbox\_unskip} + \.whatfree4 \_advance\_tmpdim by-.8pt \_ifdim\_tmpdim<\_baselineskip \_vfil\_break \_fi + \_offinterlineskip \.crule\.center4\.crule\.center5 \.printboxes + \.center5\.crule \_egroup \_goodbreak +} +\_def\.whatfree#1{\_tmpdim=\_vsize \_advance\_tmpdim by-\_pagetotal + \_advance\_tmpdim by-\_prevdepth \_advance\_tmpdim by-.4pt + \_advance\_tmpdim by-\_ht#1 \_advance\_tmpdim by-\_dp#1 \_advance\_tmpdim by-\_ht5 } +\_def\.revertbox {\_setbox0=\_lastbox\_unskip + \_ifvoid0 \_else \_global\_setbox2=\_vbox{\_unvbox2\_box0} \_ea\.revertbox\_fi} +\_def\.printboxes{\_setbox2=\_vbox{\_unvbox2 \_global\_setbox0=\_lastbox\_unskip} + \_ifvoid0 \_else \.whatfree0 + \_ifdim\_tmpdim<0pt \.center5\.crule\_vfil\_break \.crule\.center4\.crule\.center5 \_fi + \.center0 \_nobreak \.printboxes \_fi} +\_def\.crule{\_centerline{\_hbox to\_wd4{\_hrulefill}}\_nobreak} +\_def\.center#1{\_centerline{\_copy#1}\_nobreak} + +\_def\.strutT {\_vrule height1.8em depth.8em width0pt} % strut for the title + +\_trick 0032 \vcent \vbot ; +%%%%%%%%%%%% + +\_def\vbot {\_let\_tableparbox=\_vbox} +\_def\vcent {\_toksapp\_tabiteml{$}\_tokspre\_tabitemr{$}\_let\_tableparbox=\_vcenter} + +\_trick 0046 \tnote ; +%%%%%%%%%%%% + +\_newcount\.tnotenum +\_def\.tnotelist{} +\_def\.tnoteformat{$\Red^{\_rm\_athe\.tnotenum}$} +\_def\tnote#1{\_incr\.tnotenum \.tnoteformat\_global\_addto\.tnotelist{{#1}}} +\_def\tnoteprint{\_par\_noindent \.tnotenum=0 + \_ea\_foreach\.tnotelist \_do{\_advance\.tnotenum by1 \.tnoteformat##1 }\_par + \_global\.tnotenum=0 \_gdef\.tnotelist{}% +} + +\_trick 0050 \tabnodes \tablebefore ; +%%%%%%%%%%%% + +\_def\tablebefore{\_ifvmode \_nointerlineskip\_null \_fi + \_incr\.tndnum \_setpos[t\_the\.tndnum:ori:b]\_ea\.tbpxpy\_ea{\_the\.tndnum}{b}\_decr\.tndnum +} +\_def\tableafter {\_setpos[t\_the\_tndnum:ori:e]\_ea\.tbpxpy\_ea{\_the\.tndnum}{e}} +\_def\.tbpxpy#1#2{% + \_def\.tbpx[##1]{\_expr{\_bp{\_posx[t#1:##1]}-\_bp{\_posx[t#1:ori:#2]}}}% + \_def\.tbpy[##1]{\_expr{\_bp{\_posy[t#1:##1]}-\_bp{\_posy[t#1:ori:#2]}}}% +} +\_newcount\.tndnum \_newcount\.tablerownum +\_def\.putnodeh#1{\_omit\_relax + \_setpos[t\_the\.tndnum:l#1]\_hskip0pt plus1fill\_relax \_setpos[t\_the\.tndnum:r#1]} +\_def\.putnodelr{\_fornum 1..\_colnum-1\_do{\.putnodeh{##1}&}\.putnodeh{\_the\_colnum}% + \_gdef\.putnode{\_noalign{\.putnodev}}\_cr} +\_def\.putnodev{\_setpos[t\_the\.tndnum:v\_the\.tablerownum]\_incr\.tablerownum} +\_def\tabnodes{\_incr\.tndnum \.tablerownum=0 + \_def\_tablepxpreset{\_everycr{}}\_let\.putnode=\.putnodelr \_everycr={\.putnode}} + +\_def\itl[#1,#2]{\_expr{\.tbpx[l\.enum{#2}]} \_expr{\.tbpy[v\.enum{#1-1}]}} +\_def\icl[#1,#2]{\_expr{\.tbpx[l\.enum{#2}]} + \_expr{(\.tbpy[v\.enum{#1-1}]+(\.tbpy[v\.enum{#1}]))/2}} +\_def\ibl[#1,#2]{\_expr{\.tbpx[l\.enum{#2}]} \_expr{\.tbpy[v\.enum{#1}]}} +\_def\itc[#1,#2]{\_expr{(\.tbpx[l\.enum{#2}]+(\.tbpx[r\.enum{#2}]))/2} + \_expr{\.tbpy[v\.enum{#1-1}]}} +\_def\icc[#1,#2]{\_expr{(\.tbpx[l\.enum{#2}]+(\.tbpx[r\.enum{#2}]))/2} + \_expr{(\.tbpy[v\.enum{#1-1}]+(\.tbpy[v\.enum{#1}]))/2}} +\_def\ibc[#1,#2]{\_expr{(\.tbpx[l\.enum{#2}]+(\.tbpx[r\.enum{#2}]))/2} + \_expr{\.tbpy[v\.enum{#1}]}} +\_def\itr[#1,#2]{\_expr{\.tbpx[r\.enum{#2}]} \_expr{\.tbpy[v\.enum{#1-1}]}} +\_def\icr[#1,#2]{\_expr{\.tbpx[r\.enum{#2}]} + \_expr{(\.tbpy[v\.enum{#1-1}]+(\.tbpy[v\.enum{#1}]))/2}} +\_def\ibr[#1,#2]{\_expr{\.tbpx[r\.enum{#2}]} \_expr{\.tbpy[v\.enum{#1}]}} +\_def\iwd[#1,#2]{\_expr{\.tbpx[r\.enum{#2}]-(\.tbpx[l\.enum{#2}])}} +\_def\iht[#1,#2]{\_expr{\.tbpy[v\.enum{#1-1}]-(\.tbpy[v\.enum{#1}])}} + +\_def\.enum#1{\_number\_numexpr#1\_relax} +\_def\ishift #1{\_ea\.ishifta#1} % \ishift[2,3][1pt,2.5pt] +\_def\.ishifta \_expr#1 \_expr#2#3#4,#5]{\_expr{#1+(\_bp{#4})} \_expr{#2+(\_bp{#5})}} +\_def\tabpos#1#2{#1\_ifx\ishift#2\_afterfi{\_ea\_ea\_ea\_ea\_ea\_ea}\_fi\_ea\.tabposA#2} +\_def\.tabposA\_expr#1 \_expr#2{\_expr{#1}bp \_expr{#2}bp} + +\_trick 0031 \framedblocks ; +%%%%%%%%%%%% + +\_newcount\.blocklevel % nesting level of blocks +\_def\begblock{\_par\_bgroup + \_advance\.blocklevel by1 \_advance\_leftskip by\_iindent \_rightskip=\_leftskip + \_medskip + \_openref\_pdfsavepos \_ea\_wref\_ea\.Xblock\_ea{\_ea{\_the\.blocklevel}B{\_the\_pdflastypos}} + \_nobreak \_medskip +} +\_def\endblock{\_par\_nobreak\_medskip + \_pdfsavepos \_ea\_wref\_ea\.Xblock\_ea{\_ea{\_the\.blocklevel}E{\_the\_pdflastypos}} + \_medskip \_egroup +} +\_newdimen\.frtop \_newdimen\.frbottom % positions of top and bottom text on the pages +\_pgbackground={% + \_slet{_optextrick_tmp}{frm:\_the\_gpageno} + \_ifx\.tmp\_undefined \_def\.tmp{}\_fi + \.frtop=\_dimexpr \_pdfpageheight-\_voffset+\_smallskipamount\_relax + \.frbottom=\_dimexpr\_pdfpageheight-\_voffset-\_vsize-\_medskipamount\_relax + \_ifx\.frnext y \_edef\.tmp{B{\_number\.frtop}\.tmp}\_global\_let\.frnext n\_fi + \_ea\.printframes \.tmp B{0}E{\_number\.frbottom} + \_ifx\frameslist\_empty \_else + \_pdfliteral{q 1 0 0 1 0 \_bp{-\_pdfpageheight} cm \frameslist Q}\_fi +} +\_def\.printframes B#1#2E#3{\_ifnum#1=0 \_else + \printframe {\_hoffset}{#3sp}{\_xhsize}{\_ifnum#1=-1 \_number\.frtop\_else#1\_fi sp-#3sp} + \_ifx^#2^\_else \_global\_let\.frnext=y \_let\.printframes=\_relax \_fi + \_ea\.printframes\_fi +} +\_def\frameslist{} +\_ifx\printframe\_undefined +\_def\printframe #1#2#3#4{\_edef\frameslist{\frameslist + .8 g \_bp{#1} \_bp{#2} \_bp{#3} \_bp{#4} re f }% +} +\_fi +\_def\framedblocks{} % for autoloading only, it redefines standard \begblock, \endblock +\_globaldefs=0 % \refdecl needs to be processed when \localdefs=0 +\_refdecl{% + \_def\.Xblock#1#2#3{\_ifnum#1=1 \_edef\.tmp{frm:\_ea\_ignoresecond\_currpage}^^J + \_unless\_ifcsname \.tmp \_endcsname \_sxdef{\.tmp}{}\_fi^^J + \_sxdef{\.tmp}{\_cs{\.tmp}#2{#3}}\_fi} +} + +\_trick 0086 \twoblocks ; +%%%%%%%%%%%% + +\_newdimen\.pageblank +\_newdimen\.columnsht + +\_def\.setcolumn{\_advance\_hsize by-\_colsep \_hsize=.5\_hsize \_penalty0 } +\_def\twoblocks{\_par + \_begingroup \_hbadness=5000 \_splittopskip=1em plus1fil \_brokenpenalty=0 + \_setbox0=\_vbox\_bgroup \.setcolumn + \_aftergroup\.twoblocksA + \_let\.next=% +} +\_def\.twoblocksA{% + \_setbox1=\_vbox\_bgroup \.setcolumn + \_aftergroup\.twoblocksB + \_let\.next=% +} +\_def\.twoblocksB{\_setbox2=\_vsplit0 to0pt \_setbox2=\_vsplit1 to0pt \.twoblocksC} +\_def\.twoblocksC{% + \_penalty0 \_vskip\_parskip + \_ifdim\_pagegoal=\_maxdimen \.pageblank=\_vsize \_else \.pageblank=\_pagegoal \_fi + \_advance\.pageblank by-\_pagetotal + \_ifdim\.pageblank<24pt \_vfil\_break \.pageblank=\_vsize \_fi + \_ifdim\_ht0>\_ht1 \.columnsht=\_ht0 \_dimen0=\_dp0 \_else \.columnsht=\_ht1 \_dimen0=\_dp1 \_fi + \_ifdim\.columnsht>\.pageblank + \_setbox2=\_vsplit0 to\.pageblank \_setbox3=\_vsplit1 to\.pageblank + \_line{\.xvtop2\_hss\.xvtop3} + \_kern-\_baselineskip \_nobreak\_vfil\_break + \_ea\.twoblocksC + \_else + \_line{\.xvtop0\_hss\.xvtop1} + \_prevdepth=\_dimen0 + \_endgroup + \_fi +} +\_def\.xvtop#1{\_vtop{\_null\_kern-\_splittopskip\_unvbox#1}} + +\_trick 0069 \pstart ; +%%%%%%%%%%%% + +\_newcount\.firstlinenum +\_newcount\.gprevgraf + +\_def\pstart{\_par \_setbox0=\_vbox\_bgroup + \_def\_par{\_endgraf\_advance\.gprevgraf by\_prevgraf \_prevgraf=0 }} +\_def\pend{\_par \_global\_tmpnum=\.gprevgraf \_egroup + \_ifnum\.firstlinenum=0 \.firstlinenum=1 \_fi + \_advance\_tmpnum by\.firstlinenum + \.firstlinenum=\_tmpnum \_advance\_tmpnum by-1 + \_setbox0=\_vbox{\_unvbox0 + \_setbox2=\_hbox{} + \_loop + \_unskip\_unskip\_unpenalty \_setbox1=\_lastbox + \_ifvoid1 \_else + \_global\_setbox2=\_hbox{\_llap{\.pendprintnum}\_box1\_penalty0\_unhbox2} + \_advance\_tmpnum by-1 + \_repeat + }\_noindent\_unhbox2 \_par +} +\_def\.pendprintnum{\_setfontsize{mag.6}\_rm\_the\_tmpnum\_kern.8em} + +\_trick 0021 \settabs ; +%%%%%%%%%%%% + +\_def\tabs #1\cr{\_setbox0=\_hbox\_bgroup \.tabA #1&\cr&} +\_def\.tabA #1&{\_ifx\cr#1\_egroup\_box0 \_else + \_egroup + \_tmpdim=\_maxdimen \_ea\.tabB \.tabsdata {}\_relax + \_ifdim \_tmpdim=\_maxdimen \_tmpdim=0pt + \_else \_advance\_tmpdim by-\_wd0 \_fi + \_setbox0=\_hbox\_bgroup \_unhbox0 \_kern\_tmpdim \_ignorespaces#1\_unskip\_kern1sp + \_ea\.tabA \_fi +} +\_def\.tabB #1{\_ifx^#1^\_else \_unless\_ifdim \_wd0>#1 \_tmpdim=#1 \.tabC \_fi \_ea\.tabB \_fi} +\_def\.tabC #1\_relax {\_fi\_fi} + +\_def\settabs #1{\_def\.tabsdata{}\_ifx\tabs#1\_ea\.settabstext \_else\_ea\.settabscols \_fi #1} +\_def\.settabscols #1\columns{\_tmpdim=\_hsize \_divide\_tmpdim by#1\_relax + \_fornum 0..#1 \_do {\_edef\.tabsdata{\.tabsdata{\_the\_dimexpr##1\_tmpdim\_relax}}}} + +\_def\.settabstext #1#2\cr{\_setbox0=\_hbox\_bgroup \.settabA #2&\cr&} +\_def\.settabA #1&{\_ifx\cr#1\_egroup \_edef\.tabsdata{\.tabsdata{\_the\_wd0}}\_else + #1\_egroup \_edef\.tabsdata{\.tabsdata{\_the\_wd0}}% + \_setbox0=\_hbox\_bgroup \_unhbox0 + \_ea\.settabA \_fi +} +\_def\.tabsdata{} % default: no tabulators set + +\_trick 0035 \import ; +%%%%%%%%%%%% + +\_def\import#1#2{\_def\.tmp{\_gtoksapp\_picdir{#1/}\input{#2}}% + \_ea\.tmp\_ea\_global\_ea\_picdir\_ea{\_the\_picdir}} +\_def\input#1{\_input{\_the\_picdir#1}} + +\_trick 0051 \incrpp ; +%%%%%%%%%%%% + +\_openref +\_def\thepp#1{\_trycs{pp:\_csstring#1}{?\_the#1}} +\_def\thepplast#1#2{\_trycs{lastpp:\_csstring#1:#2}{?\_the#1}} +\_def\truepage{?\_the\_pageno} +\_def\incrpp#1{\_incr#1% + \_isdefined{_pgref:pp:\_csstring#1:\_the#1}\_iftrue + \_edef\.tmp{\_cs{_pgref:pp:\_csstring#1:\_the#1}}% + \_ea\_ifx\_csname currpp:\_csstring#1\_endcsname\.tmp + \_sxdef{pp:\_csstring#1}{\_the\_numexpr\_cs{pp:\_csstring#1}+1\_relax}% + \_else \_sxdef{pp:\_csstring#1}{\_trycs{resetpp:\csstring#1}{1}}% + \_sxdef{currpp:\csstring#1}{\.tmp}\_fi + \_xdef\truepage{\_ea\_ea\_ea\_usesecond \_csname currpp:\_csstring#1\_endcsname}% + \_sxdef{lastpp:\_csstring#1:\truepage}{\_cs{pp:\_csstring#1}}% + \_else \_incr\_unresolvedrefs \_openref \_fi + \_ewref \_Xlabel {{pp:\csstring#1:\the#1}{}}% +} + +\_trick 0115 \ispageodd ; + +\_def\ispageodd#1{% + \_incr\_mnotenum + \_ifcsname _mn:\_the\_mnotenum \_endcsname + \_expanded{\_let \_noexpand\.pgtype =\_cs{_mn:\_the\_mnotenum}}\_else + \_let\.pgtype=\_right \_opwarning{pageside is unknown, TeX me again}\_openref + \_fi + \_wref\_Xmnote{}% + #1\_else \_ea\_unless\_fi \_ifx\.pgtype\_right +} + +\_trick 0033 \iniseccc \seccc ; + +\_newcount \_secccnum +\_def \_thesecccnum {\_othe\_chapnum.\_the\_secnum.\_the\_seccnum.\_the\_secccnum} + +\_optdef\_seccc[]{\_trylabel \_scantoeol\_inseccc} + +\_def\_inseccc #1{\_par \_sectionlevel=4 + \_def \_savedtitle {#1}% saved to .ref file + \_ifnonum \_else {\_globaldefs=1 \_incr\_secccnum \_secccx}\_fi + \_edef \_therefnum {\_ifnonum \_space \_else \_thesecccnum \_fi}% + \_printseccc{\_scantextokens{#1}}% + \_resetnonumnotoc +} +\public \seccc ; + +\_def \_seccx {\_secccx \_secccnum=0 } +\_def \_secccx {} + +\_def\_printseccc#1{\_par + \_abovetitle{\_penalty-100}{\_medskip} + {\_bf \_noindent \_raggedright \_printrefnum[@\_quad]#1\_nbpar}% + \_nobreak \_belowtitle{\_smallskip}% + \_firstnoindent +} + +\_def\iniseccc{} % use it for autoloading the OpTeX trick code before \maketoc +\_sdef{_tocl:4}#1#2#3{\_advance\_leftskip by2\_iindent \_cs{_tocl:2}{#1}{#2}{#3}} + +\_trick 0066 \makeLOF \makeLOT \captionT \captionF ; +%%%%%%%%%%%% + +\_def\captionT [#1]#2{\_caption/t[#1]\_ewref\.Xtab{{#1}{\_thetnum}{#2}}\_ignorespaces} +\_def\captionF [#1]#2{\_caption/f[#1]\_ewref\.Xfig{{#1}{\_thefnum}{#2}}\_ignorespaces} + +\_def\.lline#1#2#3#4#5{\_line{\_hskip2em\_llap{\_bf#2 } #3 \_tocdotfill\ \_ilink[pg:#4]{#5}}} + +\_def\.makell#1#2{\_par + \_ifx#1\_undefined \_opwarning{no data for list of #2, try to run TeX again}\_openref + \_else #1\_fi +} +\_def\makeLOF{\.makell\.loflist{figures}} +\_def\makeLOT{\.makell\.lotlist{tables}} + +\_globaldefs=0 % \refdecl needs to be processed when \localdefs=0 +\_refdecl{% +\_def\.lotlist{} \_def\.loflist{}^^J +\_def\.Xtab#1#2#3{\_addto\.lotlist{\.lline{#1}{#2}{#3}}\_ea\_addto\_ea\.lotlist\_ea{\_currpage}}^^J +\_def\.Xfig#1#2#3{\_addto\.loflist{\.lline{#1}{#2}{#3}}\_ea\_addto\_ea\.loflist\_ea{\_currpage}} +} + +\_trick 0121 \correctvsize ; +%%%%%%%%%%%% + +\_def\correctvsize{% + \_vsize=\_dimexpr + \_expr[0]{\_bp{\_vsize-\_topskip}//\_bp{\_baselineskip}}\_baselineskip + +\_topskip \_relax +} + +\_trick end ; + +\_endcode + +2023-11-15 \correctvsize added +2023-11-09 \makeLOF, \makeLOT aded +2023-11-08 \ispageodd, \seccc added +2023-11-07 \settabs \import \incrpp added +2023-11-05 \twoblocks, \pstart added +2023-11-03 \framedblocks added +2023-11-01 \longtable, \vcent, \vbot, \tnote, \tabnodes added +2023-10-31 \ignoreinspic, \keystroke, \colortab, \crx, \crtop, \crbot, \crmid added +2023-10-23 \shadedframe, \roundframe added +2023-10-21 \fcread, \fullcite added +2023-10-20 \style m, \keepstyle, \easylist, \ttlineref added +2023-10-19 \directoutput, \scaleto added +2023-10-18 \algol, \cancel added +2023-10-18 \createfile added +2023-10-17 released diff --git a/macros/optex/base/optex.ini b/macros/optex/base/optex.ini index 5713354a69..b65832faf8 100644 --- a/macros/optex/base/optex.ini +++ b/macros/optex/base/optex.ini @@ -21,7 +21,7 @@ % OpTeX version -\def\optexversion{1.12 May 2023} +\def\optexversion{1.13 Nov 2023} \def\fmtname{OpTeX} \let\fmtversion=\optexversion diff --git a/macros/optex/base/optex.lua b/macros/optex/base/optex.lua index 40915fd6d4..c6ea56d794 100644 --- a/macros/optex/base/optex.lua +++ b/macros/optex/base/optex.lua @@ -675,9 +675,9 @@ local function set_node_color(n, color) -- "1 0 0 rg" or "0 g", etc. attr = tex_getcount(color_count) tex_setcount(color_count, attr + 1) local strattr = tostring(attr) - token_setmacro("_color::"..color, strattr) - token_setmacro("_color:"..strattr, color) - token_setmacro("_color-s:"..strattr, string.upper(color)) + token_setmacro("_color::"..color, strattr, "global") + token_setmacro("_color:"..strattr, color, "global") + token_setmacro("_color-s:"..strattr, string.upper(color), "global") end setattribute(todirect(n), color_attribute, attr) end diff --git a/macros/optex/base/others.opm b/macros/optex/base/others.opm index cde2f02fa1..9926c98fef 100644 --- a/macros/optex/base/others.opm +++ b/macros/optex/base/others.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \uv {Miscenaleous <2022-05-04>} % preloaded in format +\_codedecl \uv {Miscenaleous <2023-10-17>} % preloaded in format \_doc ---------------------------- \`\useOpTeX` and \`\useoptex` are declared as `\relax`. @@ -125,6 +125,46 @@ \_let \lorem=\lipsum \_doc ----------------------------- + Selected macros from \ulink[https://petr.olsak.net/optex/optex-tricks.html]{\OpTeX/ tricks} + are registered using \`\_regtrick``<cs-name>`. The <cs-name> is defined + as \^`\loadtrick` `<cs-name> <cs-name>`. When a user runs such a registered + <cs-name> then \`\loadtrick` `<cs-name>` reads the appropriate code from the + file `optex-tricks.opm` and the <cs-name> is redefined. Finally, <cs-name> is run again.\nl + The `optex-tricks.opm` file includes blocks started by \^`\_trick` followed + by the declared <cs-names> followed by semicolon followed by the code + with declarations of <cs-names> itself. The next \`\_trick` does + `\endpinput` of the file. The file is read inside temporary `\vbox` with `\globaldefs=1` + because it can be read inside horizontal mode and/or inside a group. + The `optextrick` name space is used during reading the code from + the file. Only registered control sequences are re-defined directly + in user name space.\nl + You can load a code chunk by \^`\loadtrick` `<cs-name>`. This + command doesn't run the `<cs-name>`, only loads the appropriate code. It + should be usable if you want to load the code before the fisrt usage of + the `<cs-name>`. + \_cod ----------------------------- + +\_def\_regtrick#1{\_ifx#1\_undefined\_def#1{\_loadtrick#1#1}\_else\_badtrick\_fi} +\_def\_loadtrick#1{\_resetnamespace{optextrick}\_setctable\_optexcatcodes + \_savecatcodetable\_tmpcatcodes \_catcodetable\_tmpcatcodes + \_long\_def\_loadtrickA ##1\_trick##2#1##3;{##1}% + \_wlog{Loading trick macros for \_string#1}% + \_setbox0=\_vbox{\_globaldefs=1 \_ea\_loadtrickA \_input {optex-tricks.opm}}% + \_restorectable \_endnamespace +} +\_def\_trick #1;{\_endinput} +\_public \loadtrick ; + +\_xargs \_regtrick \begfile \createfile \beglua \begLUA \logginglua + \sethours \setminutes \setseconds \setweekday \showpglists \runsystem + \directoutput \algol \scaleto \scaletof \ttlineref \easylist \keepstyle \fcread + \shadedframe \roundframe \cancel \ignoreinspic \keystroke + \colortab \crx \crtop \crbot \crmid \longtable \vcent \vbot \tnote \tabnodes \tablebefore + \framedblocks \twoblocks \pstart \settabs \import \incrpp \ispageodd + \iniseccc \seccc \makeLOF \makeLOT \captionF \captionT \correctvsize ; +\_sdef{_item:m}{\_loadtrick{\style m}\_cs{_item:m}} + + \_doc ----------------------------- Lua\TeX/ version 1.14 and newer provides `\partokenname` which allows to specify something different than `\par` at empty lines. We set `\_par` (see bellow) in \OpTeX/ version 1.04+ and newer. Some macros were rewritten @@ -198,6 +238,7 @@ \_endcode +2023-10-17 \_loadtrick introduced. 2022-05-04 \lipsum[<num>]. changed to \lipsum[<num>.] to keep macro expandable. 2022-04-21 syntax \lipsum[<num>]. introduced. 2022-02-16 declaration of @-names moved here from plain-at.opm. diff --git a/macros/optex/base/parameters.opm b/macros/optex/base/parameters.opm index c357a4ee8c..f831fa6a2d 100644 --- a/macros/optex/base/parameters.opm +++ b/macros/optex/base/parameters.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \normalbaselineskip {Parameter settings <2021-04-13>} % preloaded in format +\_codedecl \normalbaselineskip {Parameter settings <2023-09-19>} % preloaded in format \_doc ----------------------------- \secc Primitive registers @@ -57,6 +57,17 @@ \_splittopskip=10pt \_doc ----------------------------- + The following two registers were introduced to fix a couple of bugs + in the \LuaTeX/ engine. When `\matheqdirmode` is positive short + skip detection around display equations will work with right to left + typesetting. When `\breakafterdirmode` is set to 1 a glue after a dir + node will not be ignored. + \_cod ----------------------------- + +\_matheqdirmode=1 +\_breakafterdirmode=1 + + \_doc ----------------------------- \secc Plain \TeX/ registers Allocate registers that are used just like in plain \TeX/.\nl \`\smallskipamount`, \`\medskipamount`, \`\bigskipamount`, @@ -618,6 +629,7 @@ a register then \OpTeX/ macros still work without change. \_endinput History: +2023-09-19 ... \matheqdirmode and \breakafterdirmode set (relevant when RTR typesetting) 2021-04-13 ... \bibpart added 2021-04-07 ... \biboptions added, bug from iso690 fixed 2020-04-04 ... \tabspaces added diff --git a/macros/optex/base/references.opm b/macros/optex/base/references.opm index ab5ee34163..cf43bb4049 100644 --- a/macros/optex/base/references.opm +++ b/macros/optex/base/references.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \ref {References <2022-01-22>} % preloaded in format +\_codedecl \ref {References <2023-07-03>} % preloaded in format \_doc ---------------------------- \`\_Xpage` `{<gpageno>}{<pageno>}` saves the parameter pair into \`\_currpage`. @@ -66,9 +66,9 @@ are read from `\_pgref:<label>` by \`\_pgrefB``{<gpageno>}{<pageno>}{<given-text>}`. \nl \`\_lastreflabel` keeps the value of the last label read by \^`\ref` or \^`\pgref`. - You can use it for example by definig a macro `\pg` by `\def\pg{\pgref[\_lastreflabel]}` + You can use it for example by definig a macro \`\pgr` by `\def\pgr{\pgref[\_lastreflabel]}` and then you need not repeat the same label in typical situations and you - can write for instance: `see section \ref[lab] at page \pg.` + can write for instance: `see section \ref[lab] at page \pgr.` \_cod ---------------------------- \_def\_ref[#1]{\_xdef\_lastreflabel{#1}\_isnextchar\_bgroup{\_refA}{\_refA{@}}} @@ -102,12 +102,14 @@ Default \`\_printlabel` is empty macro (labels are not printed). The \`\showlabels` redefines it as box with zero dimensions and with left lapped `[<label>]` in blue 10pt `\tt` font shifted up by 1.7ex. + The color of labels is set by \`\_labelcolor` (default is RGB blue). \_cod ----------------------------- \_def\_printlabel#1{} +\_def\_labelcolor{\_setrgbcolor{0 0 1}} \_def\_showlabels {% - \_def\_printlabel##1{\_vbox to\_zo{\_vss\_llap{\_labelfont[##1]}\_kern1.7ex}}% - \_fontdef\_labelfont{\_setfontsize{at10pt}\setfontcolor{blue}\_tt} + \_def\_printlabel##1{\_vbox to\_zo{\_vss\_llap{\_labelcolor\_labelfont[##1]}\_kern1.7ex}}% + \_fontdef\_labelfont{\_setfontsize{at10pt}\_tt} } \_public \showlabels ; @@ -121,6 +123,7 @@ See section \ref[ref-file] for more information about `.ref` file concept. \_endinput +2023-07-03 ... obsolete \setfontcolor not used in \showlabels 2022-01-22 ... extended format for \ref, \pgref 2021-04-13 ... \_slideshook introduced (used by \slides) 2020-03-03 ... released diff --git a/macros/optex/base/table.opm b/macros/optex/base/table.opm index 562fe6515a..433ad41267 100644 --- a/macros/optex/base/table.opm +++ b/macros/optex/base/table.opm @@ -1,6 +1,6 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \table {Basic macros for OpTeX <2023-05-19>} % preloaded in format +\_codedecl \table {Basic macros for OpTeX <2023-06-27>} % preloaded in format \_doc ----------------------------- The result of the \`\table``{<declaration>}{<data>}` macro is inserted into @@ -418,7 +418,7 @@ \_long\_def\_frame#1{% \_hbox{\_vrule\_vtop{\_vbox{\_hrule\_kern\_vvkern - \_hbox{\_kern\_hhkern\_relax#1\_kern\_hhkern}% + \_hbox{\_kern\_hhkern{#1}\_kern\_hhkern}% }\_kern\_vvkern\_hrule}\_vrule}} \_public \frame ; @@ -591,6 +591,7 @@ after the second one. \_endinput +2023-06-27 \frame: argument in group 2023-05-19 \_tableparB,C: no strut when \tskip is processed (bug fixed). 2022-12-26 \tabdeclare: use {##} in order to allow a\over b in table items 2022-05-03 \_let\_tablereplstring\_relax removed and {...} encloses whole \_tableB body diff --git a/macros/optex/base/unimath-macros.opm b/macros/optex/base/unimath-macros.opm index d4cd9e5540..35842e674d 100644 --- a/macros/optex/base/unimath-macros.opm +++ b/macros/optex/base/unimath-macros.opm @@ -1,12 +1,13 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \loadmath {Unicode Math fonts <2023-01-17>} % preloaded in format +\_codedecl \loadmath {Unicode Math fonts <2023-09-03>} % preloaded in format \_doc ----------------------------- - \`\loadmath` `{<Unicode-math font>}` loads the given font. It does: + \`\loadmath` `<optional-factor> {<Unicode-math font>}` loads the given font. It does: \begitems * define \`\_unimathfont` as `<Unicode-math font>`, * redefine `\normalmath` and `\boldmath` macros to their Unicode counterparts, + * save the `<optional-factor>` as scaling factor, see also \^`\_mfactor`, * load the `\_unimathfont` by `\normalmath`, * print information about the loaded font on the terminal, * redefine all encoding dependent setting by `\input unimath-codes.opm`, @@ -21,16 +22,17 @@ \_def\_noloadmath{\_mathloadingfalse} \_def\_doloadmath{\_mathloadingtrue} -\_def\_loadmath#1{% +\_def\_loadmath#1#{\_loadmathA{#1}} +\_def\_loadmathA#1#2{% \_ifmathloading \_initunifonts - \_isfont{#1}\_iffalse - \_opwarning{Math font "#1" not found, skipped...}% + \_isfont{#2}\_iffalse + \_opwarning{Math font "#2" not found, skipped...}% \_else - \_def\_unimathfont{#1}% + \_sdef{_mfactor:1}{#1}\_def\_unimathfont{#2}% \_let\_normalmath = \_normalunimath \_let\_boldmath = \_boldunimath \_normalmath - \_wterm {MATH-FONT: "#1" -- unicode math prepared.}% + \_wterm {MATH-FONT: "#2" -- unicode math prepared.}% \_ifx\_ncharrmA\_undefined \_opinput {unimath-codes.opm}\_fi \_mathloadingfalse \_fi\_fi} @@ -133,9 +135,9 @@ \_def\_loadumathfamily{\_afterassignment\_loadumathfamilyA \_chardef\_mfam} \_def\_loadumathfamilyA #1#2 {\_mfactor - \_font\_mF \_umathname{#1}{\_textmff \_mparams #2} at\_sizemtext \_textfont \_mfam=\_mF - \_font\_mF \_umathname{#1}{\_scriptmff \_mparams #2} at\_sizemtext \_scriptfont \_mfam=\_mF - \_font\_mF \_umathname{#1}{\_sscriptmff\_mparams #2} at\_sizemtext \_scriptscriptfont\_mfam=\_mF + \_font\_mF \_umathname{#1}{\_textmff \_mparams #2} at\_sizemtext \_textfont \_mfam=\_mF + \_font\_mF \_umathname{#1}{\_scriptmff \_mparams #2} at\_sizemtext \_scriptfont \_mfam=\_mF + \_font\_mF \_umathname{#1}{\_sscriptmff\_mparams #2} at\_sizemtext \_scriptscriptfont \_mfam=\_mF } \_def\_textmff {ssty=0;mathsize=1;} \_def\_scriptmff {ssty=1;mathsize=2;} @@ -237,11 +239,15 @@ \_endcode -The \^`\loadmath` `{<Unicode-math font>}` macro loads math fonts and +The \^`\loadmath` `<optional-factor> {<Unicode-math font>}` macro loads the given math font and redefines all default math-codes using `\input unimath-codes.opm`. If Unicode-math font is loaded then \^`\_mathloadingfalse` is set, so the new Unicode-math font isn't loaded until \^`\doloadmath` is used. +The `<optional-factor>` is scaling factor of loaded font with respect to the +size of the text font. It can be used if the used text font and loaded math font have +incompatible ex height. If missing then the scaling factor is 1. + \^`\loadboldmath` `{<bold-font>} \to {<normal-font>}` loads bold variant only if `<normal-font>` was sucessully loaded by the previous `\loadmath`. For example: @@ -337,6 +343,9 @@ the section~\ref[math-macros]. \_endinput +2023-09-03 mathsize does work (luaotfload v. 3.36 corrected the bug +2023-08-28 mathsize doesn't work now +2023-07-03 \loadmath: optional scaling factor introduced 2023-01-17 \mathchars: \int operators re-implemented 2023-01-15 \_def\_umathrange moved to unimath-codes.opm 2023.01-15 \themathcodeclass etc. introduced diff --git a/macros/optex/base/usebib.opm b/macros/optex/base/usebib.opm index ab2f106811..cb38eea7e8 100644 --- a/macros/optex/base/usebib.opm +++ b/macros/optex/base/usebib.opm @@ -1,139 +1,285 @@ %% This is part of the OpTeX project, see http://petr.olsak.net/optex -\_codedecl \MakeReference {Reading bib databases <2022-02-04>} % loaded on demand by \usebib +\_codedecl \readbibs {Reading bib databases <2023-06-25>} % loaded on demand by \usebib \_doc ----------------------------- - Loading the `librarian.tex` macro package. See `texdoc librarian` - for more information about it. + First, we implement the scanner of `.bib` files. Unfortunately, the format of + these files isn't \TeX/ friendly, so we must to do more work. + \`\readbibs` `{<bib-bases>}` reads <bib-bases> files + (i.e. the Bib\TeX/ format). + \_cod ----------------------------- + +\_newcount\_aunum +\_newcount\_NameCount +\_def\_eaddto#1#2{\_ea\_addto\_ea#1\_ea{#2}} + +\_def\_readbibs #1{% + \_ifcsname _be:\_bibp*\_endcsname \_def\_citelist{}\_fi % \_citelist will be created + \_begingroup + \_everyeof{@{}}\_foreach#1,\_do##1,{\_ea\_nextat\_input{##1.bib}}% + \_endgroup +} +\_public \readbibs ; - We want to ignore `\errmessage` and we want not to create `\jobname.lbr` - file. + \_doc ----------------------------- + The \`\_nextat` macro skips the text in the `.bib` file to the next `@`, and starts + the \`\_bibentry` macro which reads `@<entry type>{<data>}` from the `.bib` file. + Each reference entry is conveted to the \`\_entrydata` + macro and then `\_glet \_be:<bib-part>/<label> = \_entrydata` is done. + The \^`\_entrydata` includes key-value pairs, as described in the + section~\ref[readbibs]. \_cod ----------------------------- -\_def\errmessage#1{} -\_def\newwrite#1{\_csname lb@restoreat\_endcsname \_endinput} -\_def\_tmpb{\_catcode`\_=12 \_input librarian \_catcode`\_=11 }\_tmpb -\_let\errmessage=\_errmessage -\_let\newwrite=\_newwrite +\_long\_def\_nextat#1@{\_bgroup\_catcode` =9 \_ea\_egroup\_bibentry} +\_def\_bibentry #1#{\_ifx^#1^\_else \_afterfi{\_bibentryA{#1}}\_fi} +\_def\_bibentryA #1#2{\_lowercase{\_def\_entrytype{#1}}% + \_ismacro\_entrytype{comment}\_iffalse % comment is ignored + \_ismacro\_entrytype{texcode}\_iftrue % TeX code is processed + \_endgroup #2\_begingroup \_everyeof{@{}}\_else + \_ismacro\_entrytype{string}\_iftrue % string is reported as unsupported + \_opwarning{\_string\usebib: @STRING entry isn't supported, try to use @TEXCODE}% + \_else + \_edef\_entrydata{[@]{\_entrytype}}% + {\_bibentryB #2\_fin}% % read a "normal" bib entry + \_fi\_fi\_fi + \_nextat +} +\_def\_bibentryB #1#2,#3\_fin{\_def\_citekey{#1#2}\_def\_bibentryC{\_nextfield #3,\_fin}% + \_ifcsname _be:\_bibp*\_endcsname + \_bibentryC + \_global\_addto\_citelist{\_citeI[#1#2]} + \_else + \_ea\_ifx \_begincsname _be:\_bibp#1#2\_endcsname \_empty + \_bibentryC + \_fi\_fi +} +\_def\_bibentryF {% finalize entry + \_preparebibsorting + \_global\_ea\_let \_csname _be:\_bibp\_citekey\_endcsname = \_entrydata +} -\_private \BibFile \ReadList \SortList \SortingOrder \NameCount \AbbreviateFirstname - \CreateField \RetrieveFieldInFor \RetrieveFieldIn \RetrieveField ; + \_doc ----------------------------- + \`\_nextfield` reads next field name and saves it to the \`\_fieldname` + and then reads field data and saves it to the \`\_fielddata`. + \_cod ----------------------------- + +\_def\_nextfield #1{\_ifx,#1\_ea\_nextfield % skip commas from previous field + \_else \_ifx\_fin#1\_ea\_ea\_ea\_bibentryF % finalize bib entry + \_else \_def\_fieldname{#1}\_ea\_ea\_ea\_nextfieldA % first letter of fieldname found + \_fi\_fi +} +\_def\_nextfieldA #1{% next letters of field name until = is found + \_ifx=#1\_afterfi{\_nospacefuturelet\_next\_nextfieldB}% + \_else \_addto\_fieldname{#1}% + \_ea\_nextfieldA \_fi +} +\_def\_nextfieldB {% reading field data + \_casesof\_next + " {\_nextfieldC}% name = "data", + \_bgroup {\_nextfieldD}% name = {data}, + \_finc {\_nextfieldE}% name = data, +} +\_def\_nextfieldC "#1"{\_nextfieldD{#1}} +\_def\_nextfieldD #1{\_def\_fielddata{#1}\_nextfieldF} +\_def\_nextfieldE #1,{\_nextfieldD{#1}} + +\_def\_nextfieldF{% finalize field + \_lowercase\_ea{\_ea\_def\_ea\_fieldname\_ea{\_fieldname}}% case insensitive field name + \_ifcsname _fia:\_fieldname\_endcsname \_edef\_fieldname{\_cs{_fia:\_fieldname}}\_fi + \_eaddto\_entrydata{\_ea[\_fieldname]}% + \_ismacro\_fieldname{author}\_iftrue \_ea\_auscan\_ea{\_fielddata}[author]\_else + \_ismacro\_fieldname{editor}\_iftrue \_ea\_auscan\_ea{\_fielddata}[editor]\_else + \_eaddto\_entrydata{\_ea{\_fielddata}}\_fi\_fi + \_sdef{_fd:\_fieldname\_ea}\_ea{\_fielddata}% + \_nextfield +} \_doc ----------------------------- - The `\usebib` command. + \`\_fieldalias``{<new-name>}{<given-name>}` + defines `\_fia:<new_name>` as <given-name>. \_cod ----------------------------- -\_def\_usebib/#1 (#2) #3 {% - \_let\_citeI=\_relax \_xdef\_citelist{\_trycs{_ctlst:\_bibp}{}\_trycs{_ctlstB:\_bibp}{}}% - \_global \_ea\_let \_csname _ctlst:\_bibp\_endcsname =\_write - \_ifx\_citelist\_empty - \_opwarning{No cited items. \_noexpand\usebib ignored}% - \_else - \_bgroup \_par - \_emergencystretch=.3\_hsize - \_def\_optexbibstyle{#2}% - \_setctable\_optexcatcodes - \_input bib-#2.opm - \_the \_bibtexhook - \_ifcsname _mt:bib.and:\_cs{_lan:\_the\_language}\_endcsname \_else - \_opwarning{\_string\usebib: No phrases for language - "\_cs{_lan:\_the\_language}" (using "en")}% - \_language=0 \_chardef\_documentlanguage=0 - \_fi - \_def\_tmp##1[*]##2\_relax{\_def\_tmp{##2}}\_ea\_tmp\_citelist[*]\_relax - \_ifx\_tmp\_empty\_else % there was \nocite[*] used. - \_setbox0=\_vbox{\_hsize=\_maxdimen \_def\_citelist{}\_adef@{\_readbibentry}% - \_input #3.bib - \_ea}\_ea\_def\_ea\_citelist\_ea{\_citelist}% - \_fi - \_def\_citeI[##1]{\_csname lb@cite\_endcsname{##1}{\_bibp}{}{}}\_citelist - \_BibFile{#3}% - \_if s#1\_SortList{\_bibp}\_fi - \_ReadList{\_bibp}% - \_restorectable - \_egroup - \_fi +\_def\_fieldalias#1#2{\_lowercase{\_sxdef{_fia:#1}{#2}}} + + \_doc ----------------------------- + The \`\_auscan``{<authors/editors-names>}[<field-name>]` reads the specific Bib\TeX/ + format menitoned in section~\ref[readbibs] and converts them to + `{<Lastname>}{<Firstname>}{<Von>}{<Junior>}` for each author/editor. The result + includes $4k$ subfields (where $k$ is number of the authors/editors) and + it is saved to the `\_entrydata` and the + `[authornum]{`$k$`}` or `[editornum]{`$k$`}` is added. + + The \`\_auscanA` macro does the loop over authors separated by `and`. + Each single author has its `\_tmpb` macro with `X` and `x`. Each letter + corresponds to single word of the name (`X`: begins with uppercase, `x`: + begins with lowercase). For example Leonardo Piero da Vinci has `\_tmpb` + macro `XXxX.`. If there are commas in after some words, then these commas + are in `\_tmpb` macro too, for example da Vinci, Piero Leonardo has its + `\_tmpb` macro `xX,XX.`. The number of commas is saved to `\_tmpnum`. + The \`\_auscanB` macro does a slight modifications of the `\_tmpb` macro as + mentioned in comments. Then the macro + \`\_auscanD``<tpmb-pattern>;{<WordA>}{<WordB>}{<WordC>}...` is executed. + It saves given words due to the `\_tmpb` pattern to the macros + `\_Lastname`, `\_Firstname`, `\_Von`, `\_Junior` in a loop. Finally, the contents of + these macros are saved to `\_fiedldata` and then to the `\_entrydata`. + \_cod ----------------------------- + +\_def\_auscan#1[#2]{\_def\_auname{}\_def\_fielddata{}\_def\_tmpb{}\_aunum=0\_tmpnum=0 + \_auscanA #1 and {} + \_eaddto\_entrydata{\_ea{\_fielddata}[#2num]}% + \_eaddto\_entrydata{\_ea{\_the\_aunum}}% +} +\_def\_auscanA #1 {% + \_ifx^#1^\_else + \_isequal{#1}{and}\_iftrue + \_incr\_aunum + \_addto\_tmpb{.}% + \_auscanB + \_ea\_auscanX \_auname + \_def\_auname{}\_def\_tmpb{}\_tmpnum=0 + \_else + \_lowercase{\_isequal{#1}}{#1}\_iftrue \_addto\_tmpb{x}\_else \_addto\_tmpb{X}\_fi + \_def\_tmp{#1^}\_isinlist\_tmp{,^}% + \_iftrue + \_ea\_auscanC\_tmp \_addto\_tmpb{,}\_incr\_tmpnum + \_else + \_def\_tmp{#1}% + \_fi + \_eaddto\_auname{\_ea{\_tmp}}% + \_fi + \_ea\_auscanA + \_fi +} +\_def\_auscanB{% + \_ifcase\_tmpnum % 0 commas: XXX. -> XX:X. ; XxxXX. -> X:xxXX. ; xXX. -> :xXX. ; First:Last + \_isinlist\_tmpb{x}\_iffalse \_replstring\_tmpb{X.}{:X.}\_else + \_ea\_auscanT\_tmpb;\_iffalse \_replstring\_tmpb{Xx}{X:x}\_fi\_fi + \_or % 1 comma: XX,XXX -> XX,,XXX, Junior part is empty + \_replstring\_tmpb{,}{,,}\_tmpnum=2 + \_fi % 2 commas: XX,XX,XXX no changes, generic format: Last, Junior, First + \_def\_Firstname{}\_def\_Lastname{}\_def\_Von{}\_def\_Junior{}% } -\_def\_readbibentry#1#{\_readbibentryA} -\_def\_readbibentryA#1{\_readbibentryB#1,,\_relax!.} -\_def\_readbibentryB#1#2,#3\_relax!.{\_addto\_citelist{\_citeI[#1#2]}} +\_def\_auscanT #1#2;\_iffalse{\_ifx#1x\_def\_tmpb{:x#2}\_else} % xXX. -> :xXX. +\_def\_auscanX {\_ea\_auscanD\_tmpb;} +\_def\_auscanD #1#2;{% + \_def\_tmpb{#2}% + \_casesof #1 + . {\_auscanF} % dot is last character, do final job + , {\_decr\_tmpnum \_auscanX} % Lastname->Junior or Junior->Firstname + : {\_tmpnum=2 \_auscanX} % Firstname->Lastname + X {\_auscanE\_Firstname\_Junior\_Lastname} % add data due to the \tmpnum value + x {\_auscanE\_Firstname\_Junior\_Von} % Von instead Lastname + \_finc {}% +} +\_def\_auscanE#1#2#3{\_ifcase\_tmpnum \_ea\_auscanS\_ea#1\_or \_ea\_auscanS\_ea#2\_else + \_ea\_auscanS\_ea#3\_fi} +\_def\_auscanS#1#2{% #1=\Firstname or \Lastname or etc., #2=word to be inserted + \_ifx#1\_empty \_def#1{#2}\_else \_addto#1{ #2}\_fi + \_auscanX +} +\_def\_auscanF{% final work of \auscanX + \_eaddto\_fielddata{\_ea{\_Lastname}}\_eaddto\_fielddata{\_ea{\_Firstname}}% + \_eaddto\_fielddata{\_ea{\_Von}}\_eaddto\_fielddata{\_ea{\_Junior}}% +} +\_def\_auscanC #1,^{\_def\_tmp{#1}} % removing final comma: Word,^ -> Word \_doc ----------------------------- - Corrections in librarian macros. + The \^`\_citelist` includes \`\_citeI``[<label>]` + commands. The \^`\usebib` macro runs this lists in order to print references. + Each \^`\_citeI``[<label>]` prints single bib entry given by the <label>. + It opens a group, sets macros `\_fd:<field-name>` to `<field-data>` and runs + \^`\_printentry`. Finally, it closes \TeX/ group, + so all macros `\_fd:<field-name>` have their initial (undefined) value.\nl + The \`\_getfield``[<field-name>]\macro` does `\def\macro{<field-data>}`. + If the field isn't declared then the `\macro` is empty. \_cod ----------------------------- -\_tmpnum=\_catcode`\@ \_catcode`\@=11 -\_def\lb@checkmissingentries#1,{% we needn't \errmessage here, only \opmacwarning - \_def\lb@temp{#1}% - \_unless\_ifx\lb@temp\lb@eoe - \lb@ifcs{#1}{fields}% - {}% - {\_opwarning{\_string\usebib: entry [#1] isn't found in .bib}}% - \_ea\lb@checkmissingentries - \_fi +\_def\_citeI[#1]{% + \_begingroup + \_ea\_ifx \_begincsname _be:\_bibp#1\_endcsname \_empty + \_opwarning{\_string\usebib: entry [#1] isn't found in .bib}% + \_global\_slet{_bes:#1}{_relax}% + \_else + \_ea\_ea\_ea\_foreach \_csname _be:\_bibp#1\_endcsname \_do[##1]##2{\_sdef{_fd:##1}{##2}}% + \_def\_entrykey{#1}% + \_printentry + \_fi + \_endgroup } -\_def\lb@readentry#1#2#3,{% space before key have to be ingnored - \_def\lb@temp{#2#3}% we need case sensitive keys - \_def\lb@next{\_ea\lb@gotoat\lb@gobbletoeoe}% - \lb@ifcs\lb@temp{requested}% - {\_let\lb@entrykey\lb@temp - \lb@ifcs\lb@entrykey{fields}{}% - {\lb@defcs\lb@entrykey{fields}{}% - \_lowercase{\lb@addfield{entrytype}{#1}}% - \_let\lb@next\lb@analyzeentry}}{}% - \lb@next +\_def\_getfield[#1]#2{% + \_ifcsname _fd:#1\_endcsname + \_ea\_ea\_ea \_def \_ea\_ea\_ea #2\_ea\_ea\_ea {\_csname _fd:#1\_endcsname}% + \_else \_def#2{}% + \_fi } -\_let\lb@compareA=\lb@compare -\_let\lb@preparesortA=\lb@preparesort -\_def\lb@compare#1\lb@eoe#2\lb@eoe{% SpecialSort: - \_ifx\lb@sorttype\lb@namestring - \_ifx\_sortfield\_undefined \lb@compareA#1\lb@eoe#2\lb@eoe - \_else - \_ea\_RetrieveFieldInFor\_ea{\_sortfield}\lb@entrykey\lb@temp - \_ifx\lb@temp\_empty \_toks1={#1\lb@eoe}\_else \_toks1=\_ea{\lb@temp\lb@eoe}\_fi - \_ea\_RetrieveFieldInFor\_ea{\_sortfield}\lb@currententry\lb@temp - \_ifx\lb@temp\_empty \_toks2={#2\lb@eoe}\_else \_toks2=\_ea{\lb@temp\lb@eoe}\_fi - \_edef\lb@temp{\_noexpand\lb@compareA\_space\_the\_toks1 \_space\_the\_toks2}\lb@temp - \_fi - \_else \lb@compareA#1\lb@eoe#2\lb@eoe \_fi + + \_doc ----------------------------- + \`\_preparebibsorting` is called repeatedly for each bib entry when its reading from + `.bib` file is finished. Its main goal is to do + `\gdef\_bes:<citekey> {\;<sorting-rule>^^^<citekey>}`. + Note that the part of the control sequence name after `^^^` is ignored during sorting. + The default \^`\_preparebibsorting` + macro creates <sorting-rule> in the form: <Lastnames> <Firstnames> <Von> + <Junior> of the first author followed by <year> from `year` field.\nl + \`\_dobibsorting``\_citelist` sorts the \^`\_citelist` and runs it. + \_cod ----------------------------- + +\_def\_preparebibsorting{% + \_getfield[sortedby]\_sortedby + \_ifx\_sortedby\_empty % explicitly given [sortedby] field has precedence + \_def\_sortedby{}% + \_getfield[author]\_tmp % sorting by author firstly + \_ifx\_tmp\_empty \_else \_ea\_preparebibsortingA\_tmp \_fin \_fi + \_getfield[year]\_tmp % soering by year secondly + \_ifx\_tmp\_empty \_else \_eaddto\_sortedby{\_tmp}\_fi + \_edef\_sortedby{\_sortedby}% we need to run macros aka \"e etc. + \_edef\_sortedby{\_ea\_removeoutbraces\_sortedby {\_fin}}% remove braces + \_fi + \_sxdef{_bes:\_citekey\_ea}\_ea{\_csname;\_detokenize\_ea{\_sortedby}^^^\_citekey\_endcsname}% +} +\_def\_preparebibsortingA#1#2#3#4#5\_fin {% names of the first author used by sorting: + \_def\_sortedby{#1 }% Lastname + \_ifx^#2^\_else \_addto\_sortedby{#2 }\_fi % Firstname + \_ifx^#3^\_else \_addto\_sortedby{#3 }\_fi % Von + \_ifx^#4^\_else \_addto\_sortedby{#4 }\_fi % Junior +} +\_def\_dobibsorting{% + {\_def\_citeI[##1]{\_ea\_citeIs\_csname _bes:##1\_endcsname{##1}}% + \_edef\_citelist{\_ea}\_citelist % converting \_citelist + \_dosorting\_citelist \_ea}% } -\_def\lb@preparesort#1#2\lb@eoe{% - \_if#1-% - \_def\lb@sorttype{#2}% - \_else - \_def\lb@sorttype{#1#2}% - \_fi - \lb@preparesortA#1#2\lb@eoe +\_def\_citeIs#1#2{\_eaddto\_citelist{#1}% + \_ea\_gdef#1{\_citeI[#2]\_ea\_glet#1=\_undefined \_glet#1=\_undefined}% } -\_def\_SpecialSort#1{\_def\_sortfield{#1}} -\_def\WriteImmediateInfo#1{} % the existence of .lbr file bocks new reading of .bib -\_catcode`\@=\_tmpnum \_doc ----------------------------- - Main action per each entry. + The \`\_printentry` macro prints bibliographic reference entry. + It prints <bibnum> or <bimark> (including hyperlinks) and they are + followed by printing the entry data. The format is given by the \^`\_printbib` + macro and by `\_print:<entrytype>` declared in the bib-style file. \_cod ----------------------------- -\_def\MakeReference{\_par \_bibskip - \_bibgl\_advance\_bibnum by1 +\_def\_printentry {\_par \_bibskip + \_bibgl\_incr\_bibnum \_isdefined{_bim:\_bibp\_the\_bibnum}\_iftrue \_edef\_tmpb{\_csname _bim:\_bibp\_the\_bibnum\_endcsname}% \_bibmark=\_ea{\_tmpb}% \_else \_bibmark={}\_fi - \_edef\_tmpb{\EntryKey}% - \_noindent \_dbib\EntryKey + \_edef\_tmpb{\_entrykey}% + \_noindent \_dbib\_entrykey \_printbib {% - \_RetrieveFieldIn{entrytype}\_entrytype + \_getfield[@]\_entrytype \_csname _print:BEGIN\_endcsname \_isdefined{_print:\_entrytype}\_iftrue \_csname _print:\_entrytype\_endcsname \_else \_ifx\_entrytype\_empty \_else - \_opwarning{Entrytype @\_entrytype\_space from [\EntryKey] undefined}% + \_opwarning{Entrytype @\_entrytype\_space from [\_entrykey] undefined}% \_csname _print:misc\_endcsname \_fi\_fi \_csname _print:END\_endcsname - \_wbib \EntryKey {\_the\_bibnum}{\_the\_bibmark}% + \_wbib \_entrykey {\_the\_bibnum}{\_the\_bibmark}% }\_par } @@ -147,13 +293,13 @@ \_def\_bibfieldname{#2#3}% \_if!#2\_relax \_def\_bibfieldname{#3}% - \_RetrieveFieldIn{#3}\_bibfield + \_getfield[#3]\_bibfield + \_getfield[#3num]\_namecount % total persons in the author/editor fields \_ifx\_bibfield\_empty\_else - \_RetrieveFieldIn{#3number}\_namecount - \_def\_bibfield{\_csname _Read#3\_ea\_endcsname \_csname _pp:#3\_endcsname}% + \_def\_bibfield{\_loopauthors{#3}}% read author/edior field in a loop \_fi \_else - \_RetrieveFieldIn{#2#3}\_bibfield + \_getfield[#2#3]\_bibfield \_fi \_if^#1^% \_ifx\_bibfield\_empty \_ea\_ea\_ea \_doemptyfield @@ -163,36 +309,119 @@ } \_def\_dofullfield#1#2{\_def\_dofield##1{#1}\_ea\_dofield\_ea{\_bibfield}} \_def\_doemptyfield#1#2{\_def\_dofield##1{#2}\_ea\_dofield\_ea{\_bibfield}} -\_let\_Readauthor=\ReadAuthor \_let\_Readeditor=\ReadEditor -\_def\_bprintaA #1#2{\_ifx\_bibfield\_empty #2\_else\_bprintaB #1**\_eee\_fi} -\_def\_bprintaB #1*#2*#3\_eee{\_if^#3^#1\_else\_ea\_bprintaC\_ea{\_bibfield}{#1}{#2}\_fi} +\_def\_bprintaA #1#2{\_ifx\_bibfield\_empty #2\_else\_bprintaB #1**\_fin\_fi} +\_def\_bprintaB #1*#2*#3\_fin{\_ifx^#3^#1\_else\_ea\_bprintaC\_ea{\_bibfield}{#1}{#2}\_fi} \_def\_bprintaC #1#2#3{#2#1#3} \_def\_bprintc#1#2{\_bprintcA#1#2**\_relax} \_def\_bprintcA#1#2*#3*#4\_relax{\_ifx#1\_empty \_else \_if^#4^#2\_else#2#1#3\_fi\_fi} \_def\_bprintv [#1]#2#3{\_def\_tmpa{#2}\_def\_tmpb{#3}\_bprintvA #1,,} \_def\_bprintvA #1,{% \_if^#1^\_tmpb\_else - \_RetrieveFieldIn{#1}\_tmp + \_getfield[#1]\_tmp \_ifx \_tmp\_empty \_else \_tmpa \_def\_tmpb{}\_def\_tmpa{}% \_fi \_ea \_bprintvA \_fi } -\_sdef{_pp:author}{\_letNames\_authorname} -\_sdef{_pp:editor}{\_letNames\_editorname} -\_def\_letNames{\_let\_Firstname=\Firstname \_let\_Lastname=\Lastname - \_let\_Von=\Von \_let\_Junior=\Junior -} \_doc ----------------------------- - Various macros + multilingual. Note that \`\_nobibwarnlist` is used in - \`\_bibwarning` and it is set by \^`\nobibwarning` macro. + \`\_loopauthors``{<field-name>}` does a loop over all authors/editors in + the `author` or `editor` field. The \`\_namecount` + (total nuber of authors/editors) was defined in + \^`\_bprintb`. Then for each author/edtor it do: + \begitems + * Set \`\_NameCount` to the position number of the currently processed author/editor. + * Define \`\_Lastname`, \`\_Firstname`, \`\_Junior`, \`\_Von`, \`\_After` macros. + * Run \^`\_authorname` or \^`\_editorname` macro (defined in the bib style file). + \enditems + \_cod ----------------------------- + +\_def\_loopauthors #1{% + \_NameCount=0 + \_ea\_ea\_ea\_foreach\_csname _fd:#1\_endcsname \_do ##1##2##3##4{% + \_advance\_NameCount by1 + \_def\_Lastname{##1}\_def\_Firstname{##2}\_def\_Von{##3}\_def\_Junior{##4}% + \_csname _#1ini\_endcsname \_csname _#1name\_endcsname +}} +\_def\_authorini{} % ready for \_AbbreviateFirstname or similar... +\_def\_editorini{} + + \_doc ----------------------------- + \`\_bibwarning` can be used if the manatory field is missing. + Note that \`\_nobibwarnlist` is used here, it is set by \^`\nobibwarning` macro. \_cod ----------------------------- \_def\_bibwarning{% - \_ea\_isinlist \_ea\_nobibwarnlist\_ea{\_ea,\EntryKey,}\_iffalse - \_opwarning{Missing field "\_bibfieldname" in [\EntryKey]}\_fi} + \_ea\_isinlist \_ea\_nobibwarnlist\_ea{\_ea,\_entrykey,}\_iffalse + \_opwarning{Missing field "\_bibfieldname" in [\_entrykey]}\_fi} + + \_doc ----------------------------- + \`\_AbbreviateFirstname`, \`\_RetrieveFieldIn`, \`\_RetrieveField` are here only for + backward comaptibility with previous macros based on the librarian package. + The \`\_CreateField`, \`\_SortingOrder`, and \`\_SpecialSort` are dummy + macros because the sorting is implemented by a slightly different way + than in librarian package. + \_cod ----------------------------- + +\_def\_AbbreviateFirstname{\_addto\_authorini{\_abbrevnames\_Firstname}} +\_def\_abbrevnames#1{% Karolina Pondelickova-Maslova -> K. P.-M. + \_edef#1{\_ea\_foreach #1 \_do ##1##2 {##1.% + \_foreach ##2-{}\_do ####1-####2{\_ifx^####2^\_else-####2.\_fi} }^% + }\_replstring#1{ ^}{}% +} +\_def\_RetrieveFieldIn#1{\_getfield[#1]} +\_def\_RetrieveField#1{\_trycs{_fd:#1}{}} +\_def\_CreateField#1{} +\_def\_SortingOrder#1#2{} +\_def\_SpecialSort#1{} + + \_doc ----------------------------- + The \^`\usebib` command is defined as `\input{usebib.opm}\_usebib` in the + format. So, the command is re-defined here and it is run again with the new + meaning.\nl + The \^`\usebib` macro defined here reads `\_ctlst:<bibpart>/` and `\_ctlstB:<bibpart>/` + (they include a list of `\_citeI[<label>]`) and merges them to a single \`\_citelist`. + The `\_be:<bibpart>/<label>` is set to empty for each member of the `\_citelist`. + Then the style file is read in a group, + the \^`\readbibs` macro reads given `.bib` files and resulting `\_citelist` + is processed: i.e.\ the macros \^`\_citeI` print desired entries. + \_cod ----------------------------- + +\_def\_usebib/#1 (#2) #3 {% + \_ifcsname _ctlst:\_bibp\_endcsname + \_slet{_citelist}{_ctlst:\_bibp}\_else \_def\_citelist{}\_fi + \_ea \_foreach\_citelist \_do ##1[##2]{\_sdef{_be:\_bibp##2}{}}% + \_ifcsname _ctlstB:\_bibp\_endcsname + \_ea\_ea\_ea\_foreach \_csname _ctlstB:\_bibp\_endcsname \_do ##1[##2]{% + \_ifcsname _be:\_bibp##2\_endcsname + \_else \_addto\_citelist{\_citeI[##2]}\_sdef{_be:\_bibp##2}{}% + \_fi + }% + \_fi + \_global \_ea\_let \_csname _ctlst:\_bibp\_endcsname =\_write + \_ifx\_citelist\_empty + \_opwarning{No cited items. \_noexpand\usebib ignored}% + \_else + \_bgroup + \_par + \_emergencystretch=.3\_hsize + \_def\_optexbibstyle{#2}% + \_setctable\_optexcatcodes + \_input bib-#2.opm + \_the \_bibtexhook + \_ifcsname _mt:bib.and:\_cs{_lan:\_the\_language}\_endcsname \_else + \_opwarning{\_string\usebib: No phrases for language + "\_cs{_lan:\_the\_language}" (using "en")}% + \_language=0 \_chardef\_documentlanguage=0 + \_fi + \_ifx#1c\_def\_preparebibsorting{}\_def\_dobibsorting{}\_fi + \_readbibs {#3}% + \_dobibsorting\_citelist + \_restorectable + \_egroup + \_fi +} \_endcode @@ -201,7 +430,7 @@ The file `usebib.opm` implements the command \~`\usebib/<sorttype> (<style>) <bibfiles>` where `<sorttype>` is one letter `c` (references ordered by citation order in -the text) or `s` (references ordered by key in the style file), +the text) or `s` (references sorted usually by authors and years), `<style>` is the part of the name `bib-<style>.opm` of the style file and `<bibfiles>` are one or more `.bib` file names without suffix separated by comma without space. Example: @@ -209,11 +438,10 @@ comma without space. Example: \begtt \usebib/s (simple) mybase,yourbase \endtt - This command reads the `<bibfiles>` directly and creates the list of bibliographic references (only those declared by \~`\cite[]` or -\~`\nocite[]` in the text). The formatting of such references is defined in the style -file. +\~`\nocite[]` in the document). The formatting of such references is defined in +the style~file. The principle \"first entry wins" is used. Suppose `\usebib/s (simple) local,global`. If an entry with the same label is declared in `local.bib` and in @@ -231,6 +459,7 @@ Old `.bib` files may use the obscure notation for accents like `{\"o}`. Recommendation: convert such old files to Unicode encoding. If you are unable to do this then you can set \^`\bibtexhook={`\^`\oldaccents}`. + \secc Notes for bib-style writers The `.bib` files include records in the format: @@ -244,7 +473,10 @@ The `.bib` files include records in the format: \endtt % see the file `demo/op-biblist.bib` for a real example. The <entry-types> and -<field-names> are case insensitive. +<field-names> are case insensitive. More field-names can behave equally if the +\^`\_fieldalias``{<new-field-name>}{<given-field-name>}` is used in a style +file. If a <new-field-name> is declared by this command and it is used in the `.bib` +file then the effect is the same as if it was used the <given-field-name>. Ancient Bib\TeX/ has read such files and has generated files appropriate for reading by \LaTeX. It has worked with a set of <entry-types>, see the www @@ -277,12 +509,12 @@ macros for a more comfortable setting of printing rules: * The part <if not defined> can include the \^`\_bibwarning` command if the <field-name> is mandatory. * \^`\_bprintb` `[<field-name>] {<if defined>} {<if not defined>}`. The same as - `\_bprinta`, but the `##1` parameter is used instead `*`. Differences: `##1` + \^`\_bprinta`, but the `##1` parameter is used instead `*`. Differences: `##1` parameter can be used more than once and can be enclosed in nested braces. The `*` parameter can be used at most once and cannot be enclosed - in braces. Warning: if the `\_bprintb` commands are nested (`\_bprintb` in - `\_bprintb`), then you need to write the `####1` parameter for internal `\_bprintb`. - But if `\_bprinta` commands are nested then the parameter is not duplicated. + in braces. Warning: if the \^`\_bprintb` commands are nested (`\_bprintb` in + \^`\_bprintb`), then you need to write the `####1` parameter for internal `\_bprintb`. + But if \^`\_bprinta` commands are nested then the parameter is not duplicated. * \^`\_bprintc` `\macro {<if non-empty>}`. The <if non-empty> part is executed if `\macro` is non-empty. The `*` parameter can be used, it is replaced by the `\macro`. @@ -317,17 +549,17 @@ in order to declare the format of printing each individual name. The following control sequences can be used in these macros: \begitems -* `\_NameCount`: the number of the currently processed author in the list -* `\_namecont`: the total number of the authors in the list -* `\_Lastname`, `\_Firstname`, `\_Von`, `\_Junior`: the parts of the name. +* \^`\_NameCount`: the number of the currently processed author in the list +* \^`\_namecount`: the total number of the authors in the list +* \^`\_Lastname`, \^`\_Firstname`, \^`\_Von`, \^`\_Junior`: the parts of the name. \enditems -The whole style file is read in the group during the `\usebib` command is executed +The whole style file is read in the group during the \^`\usebib` command is executed before typesetting the reference list. Each definition or setting is local here. The auto-generated phrases (dependent on current language) can be used in -bib-style files by `\_mtext{bib.<identifier>}`, where <ident> is an identifier of +bib-style files by `\_mtext{bib.<identifier>}`, where <identifier> is an identifier of the phrase and the phrase itself is defined by `\_sdef{_mt:bib.<identifier>:<language>}{<phrase>}`. See section~\ref[langphrases] for more detail. Phrases for <identifiers>: @@ -335,24 +567,14 @@ and, etal, edition, citedate, volume, number, prepages, postpages, editor, editors, available, availablealso, bachthesis, masthesis, phdthesis are defined already, see the end of section~\ref[langphrases]. -If you are using non-standard field-names in .bib database and bib-style, -you have to declare them by `\_CreateField {<fieldname>}`. - -You can declare `\_SortingOrder` in the manner documented by librarian package. - -User or author of the bib-style can create the hidden field which has a -precedence while sorting names. Example: - -\begtt -\CreateField {sortedby} -\SpecialSort {sortedby} -\endtt +The `sortedby` field is declared by \~`\readbibs` as a special field where +sorting phrase can be specified. If it is present then it has precedence +before default sorting phrase generated by \~`\_preparebibsorting` from the +lastname, firstnames of the first author and from the year. Suppose that the .bib file includes: \begtt -... author = "Jan Chadima", sortedby = "Hzzadima Jan", -... \endtt Now, this author is sorted between H and I, because the Ch digraph in this name has to be sorted by this rule. @@ -361,37 +583,91 @@ If you need (for example) to place the auto-citations before other citations, then you can mark your entries in `.bib` file by `sortedby = "@"`, because this character is sorted before `A`. +If you want to declare a different sorting rule, you can re-define the +\^`\_preparebibsorting` macro. The example is in the +\ulink[http://petr.olsak.net/optex/optex-tricks.html\#reverseyear]{\OpTeX/ trick 0113}. + +\secc[readbibs] Direct reading of `.bib` files + +\^`\readbibs` `{<bib-bases>}` is internally used (by \^`\usebib`) +for reading `.bib` databases in Bib\TeX/ format. The <bib-bases> is +comma separated list of file names (without `.bib` extension, without +spaces). These files are read and \^`\readbibs` defines macros +`\_be:<bibpart>/<label>`, where <label> is the label of the reference record. +These macros include key-value pairs `[<field name>]{<field data>}`. +The first pair is `[@]{<entry type>}`. +For example, if we have in the `.bib` file: +\begtt +@Book { tbn, + author = "Petr Olšák", + TITle = {\TeX{}book naruby}, + publisher = "Konvoj", + year = 2001, +} +\endtt +and the \^`\bibpart` is empty (default value) +then the `\_be:/tbn` macro is defined with the content: +\begtt +[@]{BOOK}[author]{{Olšák}{Petr}{}{}}[authornum]{1}[title]{\TeX{}book naruby}% +[publisher]{Konvoj}[year]{2001} +\endtt +If you do `\slet{tmp}{_be:/tbn}` then you can print the data (for example) by: +\begtt +\ea\foreach \tmp \do [#1]#2{\wterm{field-name: "#1", data: "#2"}} +\endtt +or you can do `\ea\foreach \tmp \do [#1]#2{\sdef{bib-field:#1}{#2}}` to enable +direct acces to the scanned data. + +Note that entry type and field names are converted lower-case by the `\readbibs` macro. + +There are two special entry types: `@COMMENT{<ignored text>}` and +`@TEXCODE{<processed text>}`. The <ignored text> is ignored, the +<processed text> is executed by \TeX/. The definitions of macros used in other +entries in data of fields can be here. If the `\usebib` is used then +the <processed text> is executed inside a +\TeX/ group, so the assignment is locally valid only during creating the +reference list. The BiB\TeX/'s `@STRING{}` isn't supported. All others entry +types are interpreted as a {\em reference entry} and they are interpreted as +described above. An optional balanced text between entries in `.bib` files +is ignored. + +If the macro `\_be:<bibpart>/*` is defined then the \^`\readbibs` macro reads +all entries from `.bib` files and creates \~`\_citelist`. If the +`\_be:<bibpart>/*` is undefined then +the \^`\readbibs` macro reads only entries with <label> where +`\_be:<bibpart>/<label>` is set to the empty macro. After reading, the +macros `\_be:<bibpart>/<label>` are globally re-defined as described above. + +The \^`\readbibs` macro doesn't convert fields data, but there are two exceptions: +author and editor fields. These fields have very specific format with +various alternatives, see \url{https://nwalsh.com/tex/texhelp/bibtx-23.html}. +Shortly speaking, more authors are divided by the `and` keyword and names of a single +author must be separated to four subfields: <Lastnames>, <Firstnames>, <Von>, +<Junior>. Only the <Lastnames> subfield must be nonempty. The input can look like +\begtt +Leonardo Piero da Vinci +or +da Vinci, Leonardo Piero +\endtt +and both these variants are converted to `{Vinci}{Leonardo Piero}{da}{}`. +The <Von> part is rekognized as a word with only lowercase letters. In +general, the name can be written without commas: <Firstnames> <Von> +<Lastnames> or with single comma: <Von> <Lastnames>, <Firstnames> or with two +commas: <Von> <Lastnames>, <Junior>, <Firstnames> and all these variants are +converted to the quaternion `{<Lastnames>}{<Firstnames>}{<Von>}{<Junior>}` +by the \^`\readbibs` macro. +If there are more than single author, then each author is saved in four +subfields side by side, so you have 4 or 8 or 12 etc.\ subfildeds in the +author/editor data field. You can read them by +`\foreach <author-data>\do #1#2#3#4{...}`. + \_endinput History: -------- -2022-02-04 reading tail of languages.opm removed -2021-04-30 \RetrieveField declared as private, bug fixed. -2021-04-13 \bibpart implemented -2021-04-13 \_bibgl introduced (used by \slides) -2021-03-12 \_citelistB added before first test. -2021-02-15 \_expandafter -> \_ea -Apr. 2014: released in OPmac -Jan. 2016: "first entry wins" implemented -Apr. 2016: \readentry -> \readbibentry, \usebib->\MakeReference -Feb. 2018: \input librarian does not create \jobname.lbr - -% Source: - -% opmac-bib -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Petr Olsak, version Feb. 2018 (beta) - -% This is module for OPmac macros, see http://petr.olsak.net/opmac.html -% The command: -% \usebib/<sorttype> (<style>) (bibfiles> -% for direct reading .bib files by OPmac macros (without bibTeX) is implemented here. -% The implementation depends on librarian.tex package by Paul Isambert. -% Use: -% \input opmac \input opmac-bib -% or simply: -% \input opmac-bib -% before using the command \usebib. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% end - +2023-06-25: \_fieldalias introduced +2023-06-07: bug fix (\_namecount declaration) +2023-06-06: \_slet{_bes:#1}{_relax}: bugfix when label not found and sorting +2023-06-05: @TEXCODE introduced + more consistent doc +2023-06-02: macros re-implemeted, librarian package no more needed. +2018 - 2023-06-01 usebib.opm based on librarian package, like in OPmac. |