summaryrefslogtreecommitdiff
path: root/macros/luatex/optex/base/ref-file.opm
blob: fd7c1101d76733fc6fe5e519414eb30bef131721 (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
%% This is part of the OpTeX project, see http://petr.olsak.net/optex

\_codedecl \openref {File for references <2020-02-14>} % preloaded in format

   \_doc --------------------------
   The \`\_inputref` macro is used in `\everyjob`. It reads `\jobname.ref` file
   if it exists. After the file is read then it is removed and opened to write
   a new contents to this file.
   \_cod --------------------------

\_newwrite\_reffile

\_def\_inputref {%
  \_isfile{\_jobname.ref}\_iftrue
     \_input {\_jobname.ref}
     \_gfnotenum=0 \_lfnotenum=0 \_mnotenum=0
     \_openrefA{\_string\_inputref}%
  \_fi
}

   \_doc --------------------------
   If the file does not exist then it is not created by default. It means that if you
   process a document without any forward references then no `\jobname.ref`
   file is created because it is unusable. The \^`\_wref` macro is a dummy in
   this case.
   \_cod --------------------------

\_def\_wrefrelax#1#2{}
\_let\_wref=\_wrefrelax

   \_doc ---------------------
   If a macro needs to create and to use `.ref` file then such macro must use
   \`\openref`. When the file is created (using internal \`\_openrefA`) then
   the \`\_wref` `\<macro>{<data>}` is redefined in order to
   save the line `\<macro><data>` to the `.ref` file using asynchronous
   `\write` primitive. Finally, the `\_openref` destroys itself, because we
   need not open the file again.
   \_cod ---------------------

\_def\_openref {%
  \_ifx \_wref\_wrefrelax \_openrefA{\_string\openref}\_fi
  \_gdef\_openref{}%
}
\_def\_openrefA #1{%
   \_immediate\_openout\_reffile="\_jobname.ref"\_relax
   \_gdef\_wref ##1##2{\_write\_reffile{\_bslash\_csstring##1##2}}%
   \_immediate\_write\_reffile {\_pcent\_pcent\_space OPTeX <\_optexversion> - REF file (#1)}%
   \_immediate\_wref \Xrefversion{{\_REFversion}}%
}
\def\openref{\_openref}

   \_doc ----------------------
   We are using the convention that the macros used in `.ref` file are named
   `\_X<foo>`. If there is a new version of \OpTeX/ with a different collection
   of such macros then we don't want to read the `.ref` files produced by an
   old version of \OpTeX/ or by OPmac. So the first line of `.ref` file is in
   the form
   \begtt \catcode`\<=13
   \Xrefversion{<version>}
   \endtt
   We can check the version compatibility by this macro.
   Because OPmac does not understand `\_Xrefversion` we use
   \`\Xrefversion` (with a different number of `<version>` form OPmac) here.
   The result: OPmac skips the `.ref` files produced by \OpTeX/ and vice
   versa.
   \_cod ----------------------

\_def\_REFversion{4} % actual version of .ref files in OpTeX
\_def\_Xrefversion#1{\_ifnum #1=\_REFversion\_relax \_else \_endinput \_fi}
\_public \Xrefversion ; % we want to ignore .ref files generated by OPmac

   \_doc -----------------------
   You cannot define your special `.ref` macros before `.ref` file is read
   because it is read in `\everyjob`. But you can define such macros using
   \`\refdecl``{<definitions of your ref macros>}`.
   This command sends to `.ref` file your `<definitions of your ref macros>`
   immediately. Next lines in `.ref` file should include our macros. Example
   from CTUstyle2:
   \begtt
   \refdecl{%
      \def\totlist{} \def\toflist{}^^J
      \def\Xtab#1#2#3{\addto\totlist{\totline{#1}{#2}{#3}}}^^J
      \def\Xfig#1#2#3{\addto\toflist{\tofline{#1}{#2}{#3}}}
   }
   \endtt
   We must read `<definition of your ref macros>` when the catcode of `#` is 12
   because we needn't duplicate each `#` in the `.ref` file.
   \_cod \_fin -----------------

\_def\_refdecl{\_bgroup \_catcode`\#=12 \_refdeclA}
\_def\_refdeclA #1{\egroup\_openref
   \_immediate\_write\_reffile {\_pcent\_space \_string \refdecl:}%
   \_immediate\_write\_reffile {\_detokenize{#1}}%
}
\_public \refdecl ;

\_endcode % ================================================


The `.ref` file has the name `\jobname.ref` and
it saves information about references, TOC lines, etc.
All data needed in next \TeX/ run are saved here.
\OpTeX/ reads this file at the beginning of the document
(using `\everyjob`) if such file exists.
The `.ref` file looks like:

\begtt \catcode`\<=13
\Xrefversion{<ref-version>}
\_Xpage{<gpageno>}{<pageno>}
\_Xtoc{<level>}{<type>}{<text>}<title>
\_Xlabel{<label>}{<text>}
\_Xlabel{<label>}{<text>}
...
\_Xpage{<gpageno>}{<pageno>}
\_Xlabel{<label>}{<text>}
...
\endtt
%
where <gpageno> is internal page number globally numbered from one and
`<pageno>` is a page number (`\the\pageno`) used in pagination (they may differ).
Each page begins with \^`\_Xpage`.
The `<label>` is a label used by user in `\label[<label>]` and `<text>` is a
text which should be referenced (the number of section or table, for
example `2.3.14`). The `<title>` is the title of the chapter (`<level>`=1,
`<type>`=`chap`), section (`<level>`=2, `<type>`=`sec`), subsection
(`<level>`=3, `<type>`=`secc`). The \^`\_Xpage` is written at the beginning of each
page, the `\_Xtoc` is written when chapter or section or subsection title
exists on the page and `\_Xlabel` when labeled object prefixed by
`\label[<label>]` exists on the page.

The `.ref` file is read when the processing of the document starts using
`\everyjob`. It is read, removed, and opened to writing immediately.
But the `.ref` file should be missing. If none forward references are needed
in the document then `.ref` file is not created. For example, you only want
to test a simple plain \TeX/ macro, you create `test.tex` file, you do
`optex test` and you don't need to see an empty `test.ref` file in your directory.