diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/expl3/l3xref.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/expl3/l3xref.dtx | 379 |
1 files changed, 379 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/expl3/l3xref.dtx b/Master/texmf-dist/source/latex/expl3/l3xref.dtx new file mode 100644 index 00000000000..2f03bf8b387 --- /dev/null +++ b/Master/texmf-dist/source/latex/expl3/l3xref.dtx @@ -0,0 +1,379 @@ +% \iffalse +%% File: l3xref.dtx Copyright (C) 2006 LaTeX3 project +%% +%% It may be distributed and/or modified under the conditions of the +%% LaTeX Project Public License (LPPL), either version 1.3c of this +%% license or (at your option) any later version. The latest version +%% of this license is in the file +%% +%% http://www.latex-project.org/lppl.txt +%% +%% This file is part of the ``expl3 bundle'' (The Work in LPPL) +%% and all files in that bundle must be distributed together. +%% +%% The released version of this bundle is available from CTAN. +%% +%% ----------------------------------------------------------------------- +%% +%% The development version of the bundle can be found at +%% +%% http://www.latex-project.org/cgi-bin/cvsweb.cgi/ +%% +%% for those people who are interested. +%% +%%%%%%%%%%% +%% NOTE: %% +%%%%%%%%%%% +%% +%% Snapshots taken from the repository represent work in progress and may +%% not work or may contain conflicting material! We therefore ask +%% people _not_ to put them into distributions, archives, etc. without +%% prior consultation with the LaTeX Project Team. +%% +%% ----------------------------------------------------------------------- +% +%<package>\RequirePackage{l3names} +%<*dtx|testfile> +%\fi +\def\GetIdInfo$Id: #1.dtx #2 #3-#4-#5 #6 #7$#8{% + \def\fileversion{#2}% + \def\filedate{#3/#4/#5}% +%\iffalse +%<dtx> \ProvidesFile{#1.dtx}[#3/#4/#5 v#2 #8]% +%<-dtx> \ProvidesFile{\jobname.tex}[#3/#4/#5 v#2 #8]% +%\fi +} +%\iffalse +%</dtx|testfile> +%\fi +\GetIdInfo$Id: l3xref.dtx 579 2006-11-25 23:38:03Z morten $ + {L3 Experimental cross referencing} +% +% \iffalse +%<*driver> +\documentclass{l3doc} + +\begin{document} +\DocInput{l3xref.dtx} +\end{document} +%</driver> +% \fi +% +% \title{The \textsf{l3xref} package\thanks{This file +% has version number \fileversion, last +% revised \filedate.}\\ +% Cross references} +% \author{\Team} +% \date{\filedate} +% \maketitle +% +% +% \section{Cross references} +% +% \begin{function}{\xref_set_label:n} +% \begin{syntax} +% "\xref_set_label:n" "{"<name>"}" +% \end{syntax} +% Sets a label in the text. Note that this function does not do +% anything else than setting the correct labels. In particular, it +% does not try to fix any spacing around the write node; this is a +% task for the \textsf{galley2} module. +% \end{function} +% +% \begin{function}{\xref_new:nn} +% \begin{syntax} +% "\xref_new:nn" "{"<type>"}" "{"<value>"}" +% \end{syntax} +% Defines a new cross reference type <type>. This defines the token +% list pointer |\l_xref_curr_|<type>|_tlp| with default value +% <value> which gets written fully expanded when |\xref_set_label:n| +% is called. +% \end{function} +% +% +% \begin{function}{\xref_deferred_new:nn} +% \begin{syntax} +% "\xref_deferred_new:nn" "{"<type>"}" "{"<value>"}" +% \end{syntax} +% Same as |\xref_new:n| except for this one, the value written +% happens when \TeX\ ships out the page. Page numbers use this one +% obviously. +% \end{function} +% +% \begin{function}{\xref_get_value:nn} +% \begin{syntax} +% "\xref_get_value:nn" "{"<type>"}" "{"<name>"}" +% \end{syntax} +% Extracts the cross reference information of type <type> for the +% label <name>. This operation is expandable. +% \end{function} +% +% +% \StopEventually{} +% +% \subsection{Implementation} +% +% +% We start by ensuring that the required packages are loaded. +% \begin{macrocode} +%<*package> +\RequirePackage{l3quark} +\RequirePackage{l3toks} +\RequirePackage{l3io} +\RequirePackage{l3prop} +\RequirePackage{l3int} +\RequirePackage{l3token} +%</package> +%<*initex|package> +% \end{macrocode} +% +% +% +% There are two kinds of information, namely information which is +% \emph{immediate} like a section title and then there's \emph{deferred} +% information like page numbers. Each reference type belong to one of +% these categories, which we save internally as the property lists +% |\g_xref_all_curr_immediate_fields_plist| and +% |\g_xref_all_curr_deferred_fields_plist| and the reference type +% \meta{xyz} exists as the key-info pair |\xref_|\meta{xyz}|_key| +% |{\l_xref_curr_|\meta{xyz}|_tlp}| on one of these lists. This way each +% new entry type is just added as another key-info pair. +% +% When the cross references are generated at the beginning of the +% document each will turn into a control sequence. Thus |\label{mylab}| +% will internally refer to the property list |\g_xref_mylab_plist|. +% +% The extraction of values from this property list can be done in +% several different ways but we want to keep the operation +% expandable. Therefore we use a dedicated function for each type of +% cross reference, which looks like this: +% \begin{verbatim} +% \xref_get_value_xyz_aux:w -> #1 \xref_xyz_key #2#3\q_nil{#2} +% \end{verbatim} +% This will throw away all the bits we don't need. In case |xyz| is +% the first on the |mylab| property list |#1| is empty, if it's the +% last key-info pair |#3| is empty. The value of the field can be +% extracted with the function |\xref_get_value:nn| where the first +% argument is the type and the second the label name so here it would +% be |\xref_get_value:nn| |{xyz}| |{mylab}|. +% +% \begin{macro}{\g_xref_all_curr_immediate_fields_plist} +% \begin{macro}{\g_xref_all_curr_deferred_fields_plist} +% The two main property lists for storing information. They contain +% key-info pairs for all known types. +% \begin{macrocode} +\prop_new:N \g_xref_all_curr_immediate_fields_plist +\prop_new:N \g_xref_all_curr_deferred_fields_plist +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\xref_new:nn} +% \begin{macro}{\xref_deferred_new:nn} +% \begin{macro}{\xref_new_aux:nnn} +% Setting up a new cross reference type is fairly straight forward +% when we follow the game plan mentioned earlier. +% \begin{macrocode} +\def_new:Npn \xref_new:nn {\xref_new_aux:nnn{immediate}} +\def_new:Npn \xref_deferred_new:nn {\xref_new_aux:nnn{deferred}} +\def_new:Npn \xref_new_aux:nnn #1#2#3{ +% \end{macrocode} +% First put the new type in the relevant property list. +% \begin{macrocode} + \prop_gput:ccx {g_xref_all_curr_ #1 _fields_plist} + { xref_ #2 _key } + { \exp_not:c {l_xref_curr_#2_tlp }} +% \end{macrocode} +% Then define the key to be a protected macro.\footnote{We could also +% set it equal to \cs{scan_stop:} but this just feels ``cleaner''.} +% \begin{macrocode} + \def_protected:cpn { xref_#2_key }{} + \tlp_new:cn{l_xref_curr_#2_tlp}{#3} +% \end{macrocode} +% Now for the function extracting the value of a reference. We could +% do this with a simple |\prop_if_in| thing put since we want to do +% things in an expandable way we make a separate grabber for each +% type---this is also faster. The grabber function can be defined by +% using an intricate construction of |\exp_after:NN| and other goodies +% but I prefer readable code. The end result for the input |xyz| is +% \begin{verbatim} +% \def:Npn\xref_get_value_xyz_aux:w #1\xref_xyz_key #2#3\q_nil{#2} +% \end{verbatim} +% \begin{macrocode} + \toks_set:Nx \l_tmpa_toks { + \exp_not:n { \def:cpn {xref_get_value_#2_aux:w} ##1 } + \exp_not:c { xref_#2_key } + } + \toks_use:N \l_tmpa_toks ##2 ##3\q_nil {##2} +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\xref_get_value:nn} +% Getting the correct value for a given label-type pair is a matter +% of connecting the correct grabber functions and property list. +% \begin{macrocode} +\def_new:Npn \xref_get_value:nn #1#2 { + \cs_if_really_free:cTF{g_xref_#2_plist} + {??} + { +% \end{macrocode} +% This next expansion may look a little weird but it isn't if you +% think about it! +% \begin{macrocode} + \exp_args:NcNc \exp_after:NN {xref_get_value_#1_aux:w} + \prop_use:N {g_xref_#2_plist} +% \end{macrocode} +% Better put in the stop marker. +% \begin{macrocode} + \q_nil + } +} +\def:NNn \exp_after:cc 2 { + \exp_after:NN \exp_after:NN + \cs:w #1\exp_after:NN\cs_end: \cs:w #2\cs_end: +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xref_define_label:nn} +% \begin{macro}{\xref_define_label_aux:nn} +% Define the property list for each label. We better do this in two +% steps because the special catcode regime is in effect and since +% some of the info fields are very likely to contain actual text, +% we better make sure spaces aren't ignored! As for the meaning of +% other characters then it is a possibility to also have a field +% containing catcode instructions which can then be activated with +% |\etex_scantokens:D|. +% \begin{macrocode} +\def_protected_new:Npn \xref_define_label:nn { + \group_begin: + \char_set_catcode:nn {`\ }\c_ten + \xref_define_label_aux:nn +} +% \end{macrocode} +% If the label is already taken we have a multiply defined label and +% we should do something about it. For now we don't do anything +% spectacular. +% \begin{macrocode} +\def_new:Npn \xref_define_label_aux:nn #1#2 { + \cs_if_really_free:cTF{g_xref_#1_plist} + {\prop_new:c{g_xref_#1_plist}}{\WARNING} + \toks_gset:cn{g_xref_#1_plist}{#2} + \group_end: +} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% +% \begin{macro}{\xref_set_label:n} +% Then the generic command for setting a label. We expand the +% immediate labels fully before calling the write function but make +% sure the deferred fields aren't expanded just yet. Due to property +% lists being implemented as token list registers we must expand the +% `immediate' fields twice. +% \begin{macrocode} +\def:Npn \xref_set_label:n #1{ + \def:Npx \tmp:w{\prop_use:N\g_xref_all_curr_immediate_fields_plist} + \exp_args:NNx\iow_deferred_expanded:Nn \xref_write{ + \xref_define_label:nn {#1} { + \tmp:w + \prop_use:N \g_xref_all_curr_deferred_fields_plist + } + } +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\xref_write} +% A stream for writing cross references although they do not require +% to be in a separate file. +% \begin{macrocode} +\iow_new:N \xref_write +% \end{macrocode} +% \end{macro} +% +% That's it (for now). +% \begin{macrocode} +%</initex|package> +%<*showmemory> +\showMemUsage +%</showmemory> +% \end{macrocode} +% +% +% \begin{macrocode} +%<*testfile> +\documentclass{article} +\usepackage{l3xref} +\CodeStart +\def:Npn \startrecording {\iow_open:Nn \xref_write {\jobname.xref}} +\def:Npn \DefineCrossReferences { + \group_begin: + \NamesStart + \InputIfFileExists{\jobname.xref}{}{} + \group_end: +} +\AtBeginDocument{\DefineCrossReferences\startrecording} + +\xref_new:nn {name}{} +\def:Npn \setname{\tlp_set:Nn\l_xref_curr_name_tlp} +\def:Npn \getname{\xref_get_value:nn{name}} + +\xref_deferred_new:nn {page}{\thepage} +\def:Npn \getpage{\xref_get_value:nn{page}} + +\xref_deferred_new:nn {valuepage}{\number\value{page}} +\def:Npn \getvaluepage{\xref_get_value:nn{valuepage}} + +\let:NN \setlabel \xref_set_label:n + +\CodeStop +\begin{document} +\pagenumbering{roman} + +Text\setname{This is a name}\setlabel{testlabel1}. More +text\setname{This is another name}\setlabel{testlabel2}. \clearpage + +Text\setname{This is a third name}\setlabel{testlabel3}. More +text\setname{Hello World!}\setlabel{testlabel4}. \clearpage + +\pagenumbering{arabic} + +Text\setname{Name 5}\setlabel{testlabel5}. More text\setname{Name + 6}\setlabel{testlabel6}. \clearpage + +Text\setname{Name 7}\setlabel{testlabel 7}. More text\setname{Name + 8}\setlabel{testlabel8}. \clearpage + +Now let's extract some values. \getname{testlabel1} on page +\getpage{testlabel1} with value \getvaluepage{testlabel1}. + +Now let's extract some values. \getname{testlabel 7} on page +\getpage{testlabel 7} with value \getvaluepage{testlabel 7}. +\end{document} +%</testfile> +% \end{macrocode} +% +% +% \endinput +% +% $Log$ +% Revision 1.4 2006/03/20 18:26:42 braams +% Updated the copyright notice (2006) and demoted all implementation +% sections to subsections and so on to clean up the toc for source3.tex +% +% Revision 1.3 2006/01/16 11:26:57 morten +% Minor changes +% +% Revision 1.2 2006/01/15 14:07:31 braams +% Activated \StopEventually{} +% +% Revision 1.1 2006/01/15 07:55:06 morten +% New cross reference module including test file. +% +%
\ No newline at end of file |