diff options
Diffstat (limited to 'macros/luatex/optex/base/cite-bib.opm')
-rw-r--r-- | macros/luatex/optex/base/cite-bib.opm | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/macros/luatex/optex/base/cite-bib.opm b/macros/luatex/optex/base/cite-bib.opm new file mode 100644 index 0000000000..44f8dee055 --- /dev/null +++ b/macros/luatex/optex/base/cite-bib.opm @@ -0,0 +1,258 @@ +%% This is part of OpTeX project, see http://petr.olsak.net/optex + +\_codedecl \cite {Cite, Biblioraphy <2020-03-09>} % loaded in format + + \_doc ----------------------------- + Registers used by `\cite`, `\bib` macros are declared here. + The \`\bibnum` counts the bibliography items from one. + The \`\bibmark` is used when `\nonumcitations` is set. + \_cod ----------------------------- + +\_newcount\_bibnum % the bibitem counter +\_newtoks\_bibmark % the bibmark used if \nonumcitations +\_newcount\_lastcitenum \_lastcitenum=0 % for \shortcitations +\_public \bibnum \bibmark ; + + \_doc ----------------------------- + \`\cite` `[<label>,<label>,...,<label>]` manages <labes> using `\_citeA` + and prints `[<bib-marks>]` using `\_printsavedcites`. + \nl + \`\nocite` `[<label>,<label>,...,<label>]` only manages <labels> but prints nothing. + \nl + \`\rcite` `[<label>,<label>,...,<label>]` behaves like `\cite` but prints + <bib-marks> without brackets. + \nl + \`\ecite` `[<label>]{<text>}` behaves like `\rcite [<label>]` but prints + <text> instead <bib-mark>. The <text> is hyperlinked like <bib-marks> + when `\cite` or `\rcite` is used. + The emptpty internal macro \`\_savedcites` will include the `<bib-marks>` list to + be printed. This list is set by `\_citeA` inside group and it is used by + `\_printsavedcites` in the same group. Each `\cite`/`\rcite`/`\ecite` macro + starts from empty list of <bib-marks> because new group is opened. + \_cod ----------------------------- + +\_def\_cite[#1]{{\_citeA#1,,,[\_printsavedcites]}} +\_def\_nocite[#1]{{\_citeA#1,,,}} +\_def\_rcite[#1]{{\_citeA#1,,,\_printsavedcites}} +\_def\_ecite[#1]{\_bgroup\_citeA#1,,,\_ea\_eciteB\_savedcites;} +\_def\_eciteB#1,#2;#3{\_if?#1\_relax #3\_else \_ilink[cite:#1]{#3}\_fi\_egroup} +\_def\_savedcites{} + +\_public \cite \nocite \rcite \ecite ; + + \_doc ----------------------------- + `<bib-marks>` may be numbers or a special text related to cited bib-entry. + It depends on \`\nonumcitations` and on used bib-style. The mapping from + <label> to <bib-mark> is done when `\bib` or `\usebib` is processed. + These macros store the information to + \`\_Xbib``{<label>}{<number>}{<nonumber>}` where <number> and <nonumber> are + two variants of <bib-mark> (numbered or text-like). This information is + read from `.ref` file and it is saved to macros + `\_bib:<label>` and `\_bibm:<number>`. First one includes number and second + one includes <nonumber>. The `\_lastbibnum` macro includes last number of + bib-entry used in the document. A designer can use it to set appropriate + indentation when printing the list of all bib-entries. + \_cod ----------------------------- + +\_def\_Xbib#1#2#3{\_sdef{_bib:#1}{\_bibnn{#2}&}% + \_if^#3^\_else\_sdef{_bim:#2}{#3}\_fi\_def\_lastbibnum{#2}} + + \_doc ----------------------------- + \`\_citeA` `<label>,` processes one label from list of labels given in the + parameter of `\cite`, `\nocite`, `\rcite` or `\ecite` macros. It adds the + <label> to global list `\_citelist` which will be used by `\usebib` (it + must to know what <labels> are used in the document in order to pick-up + only relevant bib-entries from the database. Because we want to save + space and not to save the same <label> to `\_citelist` twice, we + distinguish four cases: + \begitems + * `<label>` was not declared by \^`\_Xbib` and it is first such <label> in the + document: Then `\_bib:<label>` is undefined and we save label using + `\_addcitlist`, write warning on the terminal and define + `\_bib:<label>` as empty. + * `<label>` was not declared by \^`\_Xbib` but it was used previously in the + document: Then `\_bib:<label>` is empty and we do nothing (only data to + `\_savedcites` are saved). + * `<label>` was declared by \^`\_Xbib` and it is first such <label> in the + document: Then `\_bin:<label>` includes `\_bibnn{<number>}&` and we + test this case by `\if &\_bibnn{<number>}&`. This is true when `\_bibnn{<number>}` + expands to empty. The <label> is saved by `\_addcitelist` and + `\_bib:<label>` is re-defined directly as <number>. + * `<label>` was declared by \^`\_Xbib` and it was used previously in the + document. Then we do nothing (only data to `\_savedcites` are saved. + \enditems + The `\_citeA` macro runs repeatedly over whole list of <labels>. + \_cod ----------------------------- + +\_def\_citeA #1#2,{\_if#1,\_else + \_if *#1\_addcitelist{*}\_ea\_skiptorelax \_fi + \_ifcsname _bib:#1#2\_endcsname \_else + \_addcitelist{#1#2}% + \_opwarning{The cite [#1#2] unknown. Try to TeX me again}\_openref + \_addto\_savedcites{?,}\_def\_sortcitesA{}\_lastcitenum=0 + \_ea\_gdef \_csname _bib:#1#2\_endcsname {}% + \_ea\_skiptorelax \_fi + \_ea\_ifx \_csname _bib:#1#2\_endcsname \_empty + \_addto\_savedcites{?,}\_def\_sortcitesA{}\_lastcitenum=0 + \_ea\_skiptorelax \_fi + \_def\_bibnn##1{}% + \_if &\_csname _bib:#1#2\_endcsname + \_def\_bibnn##1##2{##1}% + \_addcitelist{#1#2}% + \_sxdef{_bib:#1#2}{\_csname _bib:#1#2\_endcsname}% + \_fi + \_edef\_savedcites{\_savedcites \_csname _bib:#1#2\_endcsname,}% + \_relax + \_ea\_citeA\_fi +} +\_def\_addcitelist#1{\_global\_addto\_citelist{\_citeI[#1]}} +\_def\_citelist{} + + \_doc ----------------------------- + The `<bib-marks>` (in numeric or text form) are saved in \^`\_savedcites` + macro separated by commas. + The \`\_printsavedcites` prints them by normal order or sorted if + \`\sortcitations` is specified or condensed if \`\shordcitations` is + specified.\nl + The `\sortcitations` appends the dummy number 300000 and we suppose that normal + numbers of bib-entries are less than this constant. + This constant is removed after sorting algorithm. + The \`\shortcitations` sets simply `\_lastcitenum=1`. + The macros for <bib-marks> printing follows (sorry, without detail + documentation). They are documented in `opmac-d.pdf` (but only in Czech). + \_cod ----------------------------- + +\_def\_printsavedcites{\_sortcitesA + \_chardef\_tmpb=0 \_ea\_citeB\_savedcites,% + \_ifnum\_tmpb>0 \_printdashcite{\_the\_tmpb}\_fi +} +\_def\_sortcitesA{} +\_def\_sortcitations{% + \_def\_sortcitesA{\_edef\_savedcites{300000,\_ea}\_ea\_sortcitesB\_savedcites,% + \_def\_tmpa####1300000,{\_def\_savedcites{####1}}\_ea\_tmpa\_savedcites}% +} +\_def\_sortcitesB #1,{\_if $#1$% + \_else + \_mathchardef\_tmpa=#1 + \_edef\_savedcites{\_ea}\_ea\_sortcitesC \_savedcites\_end + \_ea\_sortcitesB + \_fi +} +\_def\_sortcitesC#1,{\_ifnum\_tmpa<#1\_edef\_tmpa{\_the\_tmpa,#1}\_ea\_sortcitesD + \_else\_edef\_savedcites{\_savedcites#1,}\_ea\_sortcitesC\_fi} +\_def\_sortcitesD#1\_end{\_edef\_savedcites{\_savedcites\_tmpa,#1}} + +\_def\_citeB#1,{\_if$#1$\_else + \_if?#1\_relax??% + \_else + \_ifnum\_lastcitenum=0 % only comma separated list + \_printcite{#1}% + \_else + \_ifx\_citesep\_empty % first cite item + \_lastcitenum=#1\_relax + \_printcite{#1}% + \_else % next cite item + \_advance\_lastcitenum by1 + \_ifnum\_lastcitenum=#1\_relax % cosecutive cite item + \_mathchardef\_tmpb=\_lastcitenum + \_else % there is a gap between cite items + \_lastcitenum=#1\_relax + \_ifnum\_tmpb=0 % previous items were printed + \_printcite{#1}% + \_else + \_printdashcite{\_the\_tmpb}\_printcite{#1}\_chardef\_tmpb=0 + \_fi\_fi\_fi\_fi\_fi + \_ea\_citeB\_fi +} +\_def\_shortcitations{\_lastcitenum=1 } + +\_def\_printcite#1{\_citesep\_ilink[cite:#1]{\_citelinkA{#1}}\_def\_citesep{,\_hskip.2em\_relax}} +\_def\_printdashcite#1{\_ifmmode-\_else\_hbox{--}\_fi\_ilink[cite:#1]{\_citelinkA{#1}}} +\_def\_citesep{} + +\_def\_nonumcitations{\_lastcitenum=0\_def\_sortcitesA{}\_def\_etalchar##1{$^{##1}$}% + \_def\_citelinkA##1{\_isdefined{_bim:##1}\_iftrue \_csname _bim:##1\_endcsname + \_else ##1\_opwarning{\_noexpand\_nonumcitations + empty bibmark. Maybe bad BibTeX style}\_fi} +} +\_def\_citelinkA{} + +\_public \nonumcitations \sortcitations \shortcitations ; + + \_doc ----------------------------- + The \`\bib` `[<label>] {<optional bib-mark>}` prints one bib-entry + without reading any database. The bib-enty follows after this command. + This command counts the used `\bib`s from one by `\bibnum` counter and + saves \^`\_Xbib``{<label>}{\_the\_bibnum}{\_the\_bibmark}` into `.ref` file + immediately using `\_wbib`. This is the core of creation of mapping from + `<labels>` to `<bib-marks>`. + \_cod ----------------------------- + +\_def\_bib[#1]{\_def\_tmp{\_isnextchar={\_bibA[#1]}{\_bibmark={}\_bibB[#1]}}% + \_ea\_tmp\_romannumeral-`\.} % ignore optional space +\_def\_bibA[#1]=#2{\_bibmark={#2}\_bibB[#1]} +\_def\_bibB[#1]{\_par \_bibskip + \_advance\_bibnum by1 + \_noindent \_def\_tmpb{#1}\_wbib{#1}{\_the\_bibnum}{\_the\_bibmark}% + \_printlabel{#1}% + \_printbib \_ignorespaces +} +\_def\_wbib#1#2#3{\_dest[cite:\_the\_bibnum]% + \_ifx\_wref\_wrefrelax\_else \_immediate\_wref\_Xbib{{#1}{#2}{#3}}\_fi} + +\_public \bib ; + + \_doc ----------------------------- + The \`\_printbib` prints the bib-entry itself. You can re-define it if you + want different design. The `\_pritbib` starts in horizontal mode after + `\noindent` and after the eventual hyperlink destination is inserted. + By default, the `\_printbib` sets the indentation + by `\hangindent` and prints numeric <bib-marks> by + `\llap{[\the\bibnum]}` If `\nonumcitations` then the `\_citelinkA` is not + empty and <bib-marks> (`\the\bibnum` nor `\the\bibmark`) are not printed. + The text of bib-entry follows. User can create this text manually + using `\bib` command or it is generated automatically from a `.bib` database + by `\usebib` command. + + The vertical space between bib-entries is controlled by \`\_bibskip` macro. + \_cod ----------------------------- + +\_def \_printbib {\_hangindent=\_iindent + \_ifx\_citelinkA\_empty \_hskip\_iindent \_llap{[\_the\_bibnum] }\_fi +} +\_def \_bibskip {\_ifnum\_bibnum>0 \_smallskip \_fi} + + \_doc ----------------------------- + The \`\usebib` command is implemted in `usebib.opm` file which is loaded + when the `\usebib` command is firstly used. + The `usebib.opm` file loads the `librarian.tex` for scaning the `.bib` + files. See the section~\ref[usebib], where the file `usebib.opm` is + documented. + \_cod ----------------------------- + +\_def\_usebib{\_par \_opinput {usebib.opm} \_usebib} +\_def\usebib{\_usebib} + + \_doc ----------------------------- + The macros above works if all `\cite` (or similar) commands are used + before the `\usebib` command is used because `\usebib` prints only such + bib-entries their <labels> are saved in the `\_citelist`. But if some + `\cite` is used after `\usebib`, then `\usebib` sets `\_addcitelist` to + \`\_writeXcite`, so such `\cite` saves the information to the + `.ref`file in the format \`\_Xcite``{<label>}`. Such information are copied + to `\_citelistB` during reading `.ref` file and `\usebib` concats two + lists of <labels> from `\_citelist` and `\_citelistB` and + uses this concatenated list. + \_cod ----------------------------- + +\_def\_Xcite#1{\_addto\_citelistB{\_citeI[#1]}} +\_def\_writeXcite#1{\_openref\_immediate\_wref\_Xcite{{#1}}} +\_def\_citelistB{} + +\_endcode % ------------------------------------- + +See end of the `usebib.opm` file for documentation about creating style +files `bib-<style>.opm`. + +See end of the `bib-iso690.opm` file for large documentation about `.bib` files +structure and about usage of `iso690` bib-style. + |