%% This is part of the OpTeX project, see http://petr.olsak.net/optex \_codedecl \openref {File for references <2021-07-19>} % preloaded in format \_doc -------------------------- The \`\_inputref` macro is executed in `\everyjob`. It reads the `\jobname.ref` file, if it exists. After the file is read then it is removed and opened for writing. \_cod -------------------------- \_newwrite\_reffile \_def\_inputref {% \_isfile{\_jobname.ref}\_iftrue \_input {\_jobname.ref}% \_edef\_prevrefhash{\_mdfive{\_jobname.ref}}% \_gfnotenum=0 \_lfnotenum=0 \_mnotenum=0 \_openref \_fi } \_doc -------------------------- \`\_mdfive``{}` expands to the MD5 hash of a given file. We use it to do consistency checking of the `.ref` file. First, we read the MD5 hash of `.ref` file from previous \TeX/ run before it is removed and opened for writing again in the \^`\_inputref` macro. The hash is saved to \`\_prevrefhash`. Second, we read the MD5 hash in the \^`\_byehook` macro again and if these hashes differ, warning that \"ref file has changed" is printed. Try running `optex op-demo` twice to see the effect. \_cod -------------------------- \_def\_mdfive#1{\_directlua{optex.mdfive("#1")}} \_def\_prevrefhash{} \_doc -------------------------- If the `.ref` file does not exist, then it is not created by default. This means that if you process a document without any forward references then no `\jobname.ref` file is created (it would be unusable). The \^`\_wref` macro is a dummy in that case. \_cod -------------------------- \_def\_wrefrelax#1#2{} \_let\_wref=\_wrefrelax \_doc --------------------- If a macro needs to create and use the `.ref` file, then such macro must first use \`\openref`. It creates the file and redefines \`\_wref` `\{}` so that it saves the line `\` to the `.ref` file using the asynchronous `\write` primitive. Finally, `\_openref` destroys itself, because we don't need to open the file again.\nl `\_wref``{}` in fact does `\write\_reffile{\string}` and similarly \`\_ewref``{}` does `\write\_reffile{\string}`. \_cod --------------------- \_def\_openref {% \_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}% \_immediate\_wref \Xrefversion{{\_REFversion}}% \_ifx\_refdecldata\_empty \_else \_refdeclwrite \_fi \_gdef\_openref{}% } \_def\_ewref #1#2{\_edef\_ewrefA{#2}\_ea\_wref\_ea#1\_ea{\_ewrefA}} \_def\openref{\_openref} \_doc ---------------------- We are using the convention that the macros used in `.ref` file are named `\_X`. We don't want to read `.ref` files from old, incompatible versions of \OpTeX/ (and OPmac). This is ensured by using a version number and the \`\Xrefversion` macro at the beginning of the `.ref` file: \begtt \catcode`\<=13 \Xrefversion{} \endtt The macro checks the version compatibility. Because OPmac does not understand `\_Xrefversion` we use `\Xrefversion` (with a different number of `` than OPmac) here. The result: OPmac skips `.ref` files produced by \OpTeX/ and vice versa. \_cod ---------------------- \_def\_REFversion{6} % current 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 own `.ref` macros before `.ref` file is read because it is read in `\everyjob`. But you can define such macros by using \`\refdecl``{}`. This command writes `` to the `.ref` file. Then the next lines written to the `.ref` file can include your macros. An 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 `` while `#` has the catcode 12, because we don't want to duplicate each `#` in the `.ref` file.\nl `\refdecl` appends its data to the \`\_refdecldata` macro. It is pushed to the `.ref` file immediately only if the file is opened already. Otherwise we are waiting to `\openref` because we don't want to open the `.ref` file if it is unnecessary. \_cod \_fin ----------------- \_def\_refdecldata{} \_def\_refdecl{\_bgroup \_catcode`\#=12 \_catcode`\\=12 \_catcode`\ =12 \_refdeclA} \_def\_refdeclA#1{\_egroup \_ifx\_refdecldata\_empty\_else \_global\_addto\_refdecldata{^^J}\_fi \_global\_addto\_refdecldata{#1}% \_ifx\_openref\_empty \_refdeclwrite \_fi } \_def\_refdeclwrite{% \_immediate\_write\_reffile{\_pcent\_space \_string\refdecl:^^J\_detokenize\_ea{\_refdecldata}}% \_gdef\_refdecldata{}% } \_public \refdecl ; \_endcode % ================================================ A so called `.ref` (`\jobname.ref`) file is used to store data that will be needed in the next \TeX/ run (information about references, TOC lines, etc.). If it exists it is read by `\everyjob`, when processing of the document starts, but it is not created at all if the document doesn't need any forward references. Here are the typical contents of a `.ref` file: \begtt \catcode`\<=13 \Xrefversion{} \_Xpage{}{} \_Xtoc{}{}{}{} \_Xlabel{<label>}{<text>} \_Xlabel{<label>}{<text>} ... \_Xpage{<gpageno>}{<pageno>} \_Xlabel{<label>}{<text>} ... \endtt \begitems * \^`\_Xpage` corresponds to the beginning of a page. <gpageno> is an internal page number, globally numbered from one. `<pageno>` is the page number (`\the\pageno`) used in pagination (they may differ). * \^`\_Xtoc` corresponds to a chapter, section or subsection title on a page. `<title>` is the title of the chapter (`<level>`=1, `<type>`=`chap`), section (`<level>`=2, `<type>`=`sec`) or subsection (`<level>`=3, `<type>`=`secc`). * \^`\_Xlabel` corresponds to a labelled object on a page. `<label>` is the label provided by the user in \^`\label[<label>]`, while `<text>` is the text which should be used for the reference (section or table number, for example `2.3.14`). \enditems \_endinput History: 2021-07-19 \openrefA merged to \openref 2021-07-18 ref file consistency checking added 2021-04-13 \Xrefversion incremented (6), new format of \_Xbib 2021-02-05 \_ewref introduced 2020-02-14 released