summaryrefslogtreecommitdiff
path: root/macros/luatex/optex/base/cite-bib.opm
diff options
context:
space:
mode:
Diffstat (limited to 'macros/luatex/optex/base/cite-bib.opm')
-rw-r--r--macros/luatex/optex/base/cite-bib.opm258
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.
+