summaryrefslogtreecommitdiff
path: root/macros/optex/base/cite-bib.opm
blob: 56954a4ee084a9c3915f483697ac94c371f3fe24 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
%% This is part of the OpTeX project, see http://petr.olsak.net/optex

\_codedecl \cite {Cite, Biblioraphy <2021-04-13>} % 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 -----------------------------
   \`\_bibp` expands to \^`\bibpart``/`.
   By default, \^`\bibpart` is empty, so internal links are in the form
   `cite:/<number>`. If \^`\bibpart` is set to `<bibpart>`, then internal
   links are `cite:<bibpart>/<number>`.
   \_cod -----------------------------

\_def\_bibp{\_the\_bibpart/}             % unique name for each bibliography list

   \_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 empty internal macro \`\_savedcites` will include the `<bib-marks>` list to
   be printed. This list is set by `\_citeA` inside a 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:\_bibp#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``{<bibpart>}{<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:<bibpart>/<label>` and `\_bim:<bibpart>/<number>`.
   First one includes <number> and second one includes <nonumber>.
   The `\_lastbn:<bibpart>` macro includes last number of
   bib-entry used in the document with given <bibpart>.
   A designer can use it to set appropriate
   indentation when printing the list of all bib-entries.
   \_cod -----------------------------

\_def\_Xbib#1#2#3#4{\_sxdef{_bib:#1/#2}{\_bibnn{#3}&}%
   \_if^#4^\_else\_sxdef{_bim:#1/#3}{#4}\_fi\_sxdef{_lastbn:#1}{#3}}

   \_doc -----------------------------
   \`\_citeA` `<label>,` processes one label from the list of labels given in the
   parameter of `\cite`, `\nocite`, `\rcite` or `\ecite` macros. It adds the
   <label> to a global list `\_ctlst:<bibpart>/` which will be used by `\usebib` (it
   must know what <labels> are used in the document to pick-up
   only relevant bib-entries from the database. Because we want to save
   space and to avoid duplications of <label> in the `\_ctlst:<bibpart>/`, we
   distinguish four cases:
   \begitems
   * `<label>` was not declared by \^`\_Xbib` before and it is first such a <label> in the
     document: Then `\_bib:<bibpart>/<label>` is undefined and we save label using
     \^`\_addcitelist`, write warning on the terminal and define
     `\_bib:<bibpart>/<label>` as empty.
   * `<label>` was not declared by \^`\_Xbib` before but it was used previously in the
     document: Then `\_bib:<bibpart>/<label>` is empty and we do nothing (only data to
     `\_savedcites` are saved).
   * `<label>` was declared by \^`\_Xbib` before and it is first such <label>
     used in the document: Then `\_bib:<bibpart>/<label>` includes \`\_bibnn``{<number>}&` and we
     test this case by the command `\if &\_bibnn{<number>}&`. This is true when `\_bibnn{<number>}`
     expands to empty. The <label> is saved by \^`\_addcitelist` and
     `\_bib:<bibpart>/<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 the whole list of <labels>.
   \_cod -----------------------------

\_def\_citeA #1#2,{\_if#1,\_else
   \_if *#1\_addcitelist{*}\_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
      \_incr\_unresolvedrefs
      \_addto\_savedcites{?,}\_def\_sortcitesA{}\_lastcitenum=0
      \_ea\_gdef \_csname _bib:\_bibp#1#2\_endcsname {}%
      \_ea\_skiptorelax \_fi
   \_ea\_ifx \_csname _bib:\_bibp#1#2\_endcsname \_empty
      \_addto\_savedcites{?,}\_def\_sortcitesA{}\_lastcitenum=0
      \_ea\_skiptorelax \_fi
   \_def\_bibnn##1{}%
   \_if &\_csname _bib:\_bibp#1#2\_endcsname
      \_def\_bibnn##1##2{##1}%
      \_addcitelist{#1#2}%
      \_sxdef{_bib:\_bibp#1#2}{\_csname _bib:\_bibp#1#2\_endcsname}%
   \_fi
   \_edef\_savedcites{\_savedcites \_csname _bib:\_bibp#1#2\_endcsname,}%
   \_relax
   \_ea\_citeA\_fi
}
\_let\_bibnn=\_relax

   \_doc ----------------------------
   Because we implement possibility of more independent bibliography lists
   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
   right records from `.bib` file. Then \^`\usebib` sets
   `\_ctlst:<bibpart>/` to `\_write`.\nl
   If `\_addcitelist` is processed after \^`\usebib`, then
   \`\_Xcite``{<bibpart>/}{<label>}` is saved to the `.ref`
   file. The `\_Xcite` creates `\_ctlstB:<bibpart>/` as a list of saved
   `\_citeI[<label>]`. Finally, \^`\usebib` concats boths lists `\_ctlst:<bibpart>/`
   and `\_ctlstB:<bibpart>/` in the second \TeX/ run.
   \_cod ----------------------------

\_def\_addcitelist#1{%
   \_unless \_ifcsname _ctlst:\_bibp\_endcsname \_sxdef{_ctlst:\_bibp}{}\_fi
   \_ea \_ifx \_csname _ctlst:\_bibp\_endcsname \_write
       \_openref \_immediate\_wref\_Xcite{{\_bibp}{#1}}%
   \_else \_global \_ea\_addto \_csname _ctlst:\_bibp\_endcsname {\_citeI[#1]}\_fi
}
\_def\_Xcite#1#2{%
   \_unless \_ifcsname _ctlstB:#1\_endcsname \_sxdef{_ctlstB:#1}{}\_fi
   \_global \_ea\_addto \_csname _ctlstB:#1\_endcsname {\_citeI[#2]}%
}

   \_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 the 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:\_bibp#1]{\_citelinkA{#1}}\_def\_citesep{,\_hskip.2em\_relax}}
\_def\_printdashcite#1{\_ifmmode-\_else\_hbox{--}\_fi\_ilink[cite:\_bibp#1]{\_citelinkA{#1}}}
\_def\_citesep{}

\_def\_nonumcitations{\_lastcitenum=0\_def\_sortcitesA{}\_def\_etalchar##1{$^{##1}$}%
   \_def\_citelinkA##1{\_trycs{_bim:\_bibp##1}
       {##1\_opwarning{\_noexpand\nonumcitations + empty bibmark. Maybe bad bib-style}}}%
}
\_def\_citelinkA{}

\_public \nonumcitations \sortcitations \shortcitations ;

   \_doc -----------------------------
   The \`\bib` `[<label>]` or `\bib [<label>] ={<bib-mark>}` prints one bib-entry
   without reading any database. The bib-entry follows after this command.
   This command counts the used `\bib`s from one by `\bibnum` counter and
   saves \^`\_Xbib``{<bibpart>}{<label>}{<number>}{<nonumber>}` into `.ref` file
   immediately using \`\_wbib``{<label>}{<number>}{<nonumber>}`.
   This is the core of creation of mapping from `<labels>` to `<number>` and
   `<nonumber>`.\nl
   \`\_bibA` and \`\_bibB` implement the scanner of the optional argument
   with the \^`\bibmark`.\nl
   \`\_bibgl` is `\relax` by default but \^`\slides` do `\let\_bibgl=\_global`.\nl
   \`\_dbib``{<label>}` creates destination for hyperlinks.
   \_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
   \_bibgl\_advance\_bibnum by1
   \_noindent \_def\_tmpb{#1}\_dbib{#1}\_wbib{#1}{\_the\_bibnum}{\_the\_bibmark}%
   \_printbib \_ignorespaces
}
\_def\_dbib#1{\_dest[cite:\_bibp\_the\_bibnum]\_printlabel{#1}}
\_def\_wbib#1#2#3{%
   \_ifx\_wref\_wrefrelax\_else \_immediate\_wref\_Xbib{{\_the\_bibpart}{#1}{#2}{#3}}\_fi
   \_unless \_ifcsname bib:\_bibp#1\_endcsname \_Xbib{\_the\_bibpart}{#1}{#2}{#3}\_fi
}
\_let\_bibgl=\_relax

\_public \bib ;

   \_doc -----------------------------
   The \`\_printbib` prints the bib-entry itself. You can re-define it if you
   want a 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 implemented in `usebib.opm` file which is loaded
   when the `\usebib` command is used first.
   The `usebib.opm` file loads the `librarian.tex` for scanning 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 ------------------------------
   \_forwardlink\`\nobibwarning` `[<list of bib-labels>]`
   declares a list of bib labels
   which are not fully declared in `.bib` file but we want to suppress the
   warning about it. List of bib labels are comma-separated case sensitive
   list without spaces.
   \_cod ------------------------------

\_def\_nobibwarnlist{,}
\_def\_nobibwarning[#1]{\_global\_addto\_nobibwarnlist{#1,}}
\_public \nobibwarning ;

\_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 the usage of `iso690` bib-style.

History:
2021-04-13 ... \bibpart implemented
2021-04-13 ... \_bibgl introduced (used in \slides)
2020-03-09 ... released