Chapter 13: Control Package Dependencies with scrlfile
335
\begin{figure}
\caption{This is an example for a fairly long figure caption, but
which does not employ the optional caption argument that would
allow one to write a short caption in the list of figures.}
\end{figure}
\end{document}
If now the hyperref drivers hypertex or dvips are used, then the useful hyperref
option linktocpage will be set. In the pdfL
A
TEX case, the option will not be set,
since in that case another hyperref driver, hpdftex.def, will be used. That means
neither hdvips.def nor hypertex.def will be loaded.
Furthermore, the loading of package scrlfile and the
\AfterFile
statement can be writ-
ten in a private hyperref.cfg. If you do so, then instead of \usepackage the macro
\RequirePackage
ought be used (see [
Tea06
]). The new lines have to be inserted directly
after the \ProvidesFile line, thus immediately prior to the execution of the options dvips
or pdftex.
\BeforeClosingMainAux{instructions }
\AfterReadingMainAux{instructions }
Package authors often want to write something into the aux-file after the last document page
have been shipped out. To do so, often
\AtEndDocument{%
\if@filesw
\write\@auxout{%
\protect\writethistoaux%
}%
\fi
}
is used. Nevertheless this is not a real solution of the problem. If the last page of the document
already have been shipped out before \end{document}, the code above will not result in any
writing into the aux-file. If someone would try to fix this new problem using \immediate just
before \write, the inverse problem would occur: If the last page was not shipped out before
\end{document}
the \writethistoaux would be written into aux-file before ship-out the last
page. Another often seen suggestion for this problem therefore is:
\AtEndDocument{%
\if@filesw
\clearpage
\immediate\write\@auxout{%
\protect\writethistoaux%
}%
\fi
Chapter 13: Control Package Dependencies with scrlfile
336
}
This suggestion has a disadvantage again: The ship-out of the last page has been enforced by
the
\clearpage
. After that, instructions like
\AtEndDocument{%
\par\vspace*{\fill}%
Note at the end of the document.\par
}
would not any longer output the note at the end of the last page of the document but at the
end of one more page. Additionally \writethistoaux would be written one page to early into
the aux-file again.
The best solution for this problem would be, to write to the aux-file immediately after the
final
\clearpage
, that is part of \end{document}, but just before closing the aux-file. This
is the purpose of \BeforeClosingMainAux:
\BeforeClosingMainAux{%
\if@filesw
\immediate\write\@auxout{%
\protect\writethistoaux%
}%
\fi
}
This would be successful even if the final
\clearpage
inside of \end{document} would
not really ship-out any page or if someone have had used
\clearpage
in the argument of
\AtEndDocument
.
Nevertheless there one important limitation using \BeforeClosingMainAux: You should
not use a typeset instruction inside the instructions of \BeforeClosingMainAux! If you
miss this limitation the result would be as unpredictable as the results of the problematic
suggestions using \AtEndDocument upward.
Command \AfterReadingMainAux
v3.03
actually executes the instructions just after closing
and input of the aux-file inside of \end{document}. This will make sense only in some cases,
e. g., to show statistic information, that will be valid only after input of the aux-file, or to
write such information into the log-file, or to implement additional rerun requests. Typeset
instructions are even more critical inside these instructions that inside the argument of
\BeforeClosingMainAux
.
13.3. Replacing Files at Input
All previous sections in this chapter describe commands to execute instructions before or after
input of a file, class, or package. Package scrlfile also provides commands to input another
file, class, or package instead of the one, that has been declared.
Chapter 13: Control Package Dependencies with scrlfile
337
\ReplaceInput{source file name }{replacement file name }
This
v2.96
command defines a replacement for the file of the first argument: source file name ,
by the file of the second argument: replacement file name . If L
A
TEX will be instructed to
input the file with source file name at any time afterward, the file with the replacement
file name
will be input instead. The replacement definition will be valid for all files, that the
user will input with \InputIfFileExists and for all files, that will be input with a command,
that uses \InputIfFileExists internally. To do so, scrlfile redefined \InputIfFileExists.
Example: You want L
A
TEX to input file \jobname.xua instead of file \jobname.aux. This
may be done using
\ReplaceInput{\jobname.aux}{\jobname.xua}
Additionally you may replace \jobname.xua by \jobname.uxa using:
\ReplaceInput{\jobname.xua}{\jobname.uxa}
This will also replace input of \jobname.aux, i. e., while \end{document}, by
\jobname.uxa
. As you see, the whole replacement chain will be executed.
Nevertheless a round robin replacement like
\ReplaceInput{\jobname.aux}{\jobname.xua}
\ReplaceInput{\jobname.xua}{\jobname.aux}
would result in a stack size error. So it is not possible to define a replacement of
a file by itself directly or indirectly.
In theory is would also be possible to replace a package or class by another one. But L
A
TEX
would recognize the usage of the wrong file name in this case. A solution for this problem will
be shown next.
\ReplaceClass{source class }{replacement package }
\ReplacePackage{source package }{replacement package }
Classes
v2.96
or packages should never be replaced using previously described command
\ReplaceInput
. Using this command would result in a L
A
TEX warning because of class or
package name not according the file name.
Example: You replace package fancyhdr by package scrpage2 inconsiderately using
\ReplaceInput{fancyhdr.sty}{scrpage2.sty}
Loading fancyhdr, would result in
LaTeX warning: You have requested ‘scrpage2’,
but the package provides ‘fancyhdr’.
Chapter 13: Control Package Dependencies with scrlfile
338
after this. Users may be confused by such a warning, because they’ve used, e. g.,
\usepackage{fancyhdr}
and never requested package scrpage2 on their own. But
scrlfile replaced the input of fancyhdr.sty by scrpage2.sty because of your re-
placement definition.
A solution for this problem would be, to use \ReplaceClass or \ReplacePackage instead of
\ReplaceInput
. Please note, that in this case you have to use the names of the classes or
packages only instead of the whole file name. This is similar to usage of \documentclass and
\usepackage
.
The class replacement would perform for all classes, that will be loaded us-
ing \documentclass, \LoadClassWithOptions, or \LoadClass.
The package re-
placement would perform for all packages, that will be loaded using \usepackage,
\RequirePackageWithOptions
, or \RequirePackage.
Please note, that the replacement class or the replacement package will be loaded
with the same options, the source class or replacement class would until it has been
replaced. Replacement of a class or package by a class or package, that does not support a
requested option, would result in a warning or even an error message. But you may declare
such missing options using
\BeforeClass
or
\BeforePackage
.
Example: Assumed, package oldfoo should be replaced by newfoo. This may be done using:
\ReplacePackage{oldfoo}{newfoo}
Assumed the old package provides an option oldopt, but the new package does
not. Using
\BeforePackage{newfoo}{%
\DeclareOption{oldopt}{%
\PackageInfo{newfoo}%
{option ‘oldopt’ not supported}%
}}%
additionally, would declare this missing option for package newfoo. This would
avoid warning message about unsupported options.
However, if package newfoo supports an option newopt, that should be used instead
of option oldopt of old package oldfoo, this may achieved using:
\BeforePackage{newfoo}{%
\DeclareOption{oldopt}{%
\ExecuteOptions{newopt}%
}}%
Last but not least different default options may be selected, that should be valid
while package replacement:
\BeforePackage{newfoo}{%
Chapter 13: Control Package Dependencies with scrlfile
339
\DeclareOption{oldopt}{%
\ExecuteOptions{newopt}%
}%
\PassOptionsToPackage{newdefoptA,newdefoptB}%
{newfoo}%
}
or somehow more directly:
\ BeforePackage{newfoo}{ %
\DeclareOption{oldopt}{%
\ExecuteOptions{newopt}%
}%
}%
\PassOptionsToPackage{newdefoptA,newdefoptB}%
{newfoo}%
To replace classes package scrlfile has to be loaded before the class using \RequirePackage
instead of \usepackage.
\UnReplaceInput{file name }
\UnReplacePackage{package }
\UnReplaceClass{class }
A
v3.12
replacement definition can be removed using one of these commands. The replacement
definition of a input file should be removed using \UnReplaceInput, the replacement definition
of a package should be removed using \UnReplacePackage, and the replacement definition of
a class should be removed using \UnReplaceClass.
13.4. Prevent File Loading
Especially
v3.08
classes or packages, that have been made for companies or institutes, often load a
lot of packages not needed by the classes or packages itself but only because the users often
use them. Now, if such a not essential package causes any kind of problem, loading of that
package has to prevented. For this purpose scrlfile again provides a solution.
\PreventPackageFromLoading[instead code ]{package list }
\PreventPackageFromLoading*[instead code ]{package list }
Calling this command
v3.08
before loading a package using \usepackage, \RequirePackage, or
\RequirePackageWithOptions
will prevent the package from being loaded effectively if the
package is part of the package list .
Example: Assumed you’re working in a company, that uses font Latin-Modern for all kind
of documents. Because of this the company class, compycls contains the lines:
Chapter 13: Control Package Dependencies with scrlfile
340
\RequirePackage[T1]{fontenc}
\RequirePackage{lmodern}
But now, you want to use X E L
A
TEX oder LuaL
A
TEX the first time. In this case
loading of fontenc would not be a good suggestion and Latin-Modern would be the
default font of the recommended package fontspec. Because of this you want to
prevent both packages from being loaded. This may be done, loading the class like
this:
\ RequirePackage{scrlfile}
\PreventPackageFromLoading{fontenc,lmodern}
\documentclass{firmenci}
The example above also shows, that package scrlfile may be loaded before the class. In this
case \RequirePackage has to be used, because \usepackage before \documentclass is not
permitted.
If package list is empty or contains a package, that already has been loaded,
\PreventPackageFromLoading
will warn. If you’d prefer an info
v3.12
at the log-file only, you
may use \PreventPackageFromLoading* instead.
The optional argument
v3.12
may be used to execute code instead of loading the package. But
you must not load another packages or files inside instead code . See
\ReplacePackage
in
section 13.2
on
page 337
for information about replacing a package by another one. Note also,
that the instead code will be executed several times, if you try to load the package more
than once!
\StorePreventPackageFromLoading{\command}
\ResetPreventPackageFromLoading
\StorePreventPackageFromLoad
v3.08
defines \command to be the current list of
packages, that should be prevented from being loaded.
In opposite to this,
\ResetPreventPackageFromLoading
v3.08
resets the list of packages, that should be pre-
vented from being loaded. After \ResetPreventPackageFromLoading all packages may be
loaded again.
Example: Assumed, you really need a package inside your own package and you want the user
inhibit to prevent loading of that package with
\PreventPackageFromLoading
.
Because of this, you reset the package preventing list before loading the package:
\ ResetPreventPackageFromLoading
\RequirePackage{foo}
Unfortunately the complete prevention list of the user would be lost after that. To
avoid this, you first store the list and restore it at the end:
\newcommand*{\Users@PreventList}{}%
\StorePreventPackageFromLoading\Users@PreventList
Chapter 13: Control Package Dependencies with scrlfile
341
\ResetPreventPackageFromLoading
\RequirePackage{foo}
\PreventPackageFromLoading{\Users@PreventList}
Please
note,
that
\StorePreventPackageFromLoading
would
define
\Users@PreventList
even if it already has been defined before.
In other
words: \StorePreventPackageFromLoading overwrites existing \command defini-
tions without care. Because of this, \newcommand* has been used in the example
to get an error message, if \Users@PreventList has already been defined.
At this point please note, that everybody who manipulates the list, that has been stored using
\StorePreventPackageFromLoading
is responsible for the correct restorability. For example
the list elements must be separated by comma, must not contain white space or group braces,
and must be fully expandable.
Please note, that \ResetPreventPackageFromLoading does not clean the instead code
of a package. Only the execution is not done as long as the prevention is not reactivated.
\UnPreventPackageFromLoading{package list }
\UnPreventPackageFromLoading*{package list }
Instead
v3.12
of resetting the whole list of packages, that should prevented from being loaded, you
may also remove some packages from that list. The star version of the command does also
clean the instead code . So reactivation of the prevent package list, e. g., from a stored one,
will not reactivate the instead code of the packages.
Example: Assuming, you want to prevent a package foo from being loaded, but you do not
want an already stored instead code to be executed. Instead of that code, you’re
own instead code should be executed. You can do this:
\UnPreventPackageFromLoading*{foo}
\PreventPackageFromLoading[\typeout{Stattdessencode}]{foo}
For \UnPreventPackageFromLoading it does not matter whether or not the pack-
age has been prevented from being loaded before.
Surely you can use the command also to remove only the instead code of all
packages:
\StorePreventPackageFromLoading\TheWholePreventList
\UnPreventPackageFromLoading*{\TheWholePreventList}
\PreventPackageFromLoading{\TheWholePreventList}
In this case the packages, that has been prevented from being loaded, are still
prevented from being loaded, but their instead code has been cleaned and will
not be executed any longer.
Chapter 14: Economise and Replace Files Using scrwfile
342
Economise and Replace Files Using scrwfile
TEX supports 18 write handles only. Handle 0 is used by TEX itself (log file). L
A
TEX needs
at least handle 1 for \@mainaux, handle 2 for \@partaux, one handle for \tableofcontents,
one handle for \listoffigures, one handle for \listoftables, one handle for \makeindex.
So there are 11 left. Seams a lot and enough. But every new type of float, every new index
and several other packages, e.g., hyperref need write handles, too.
The bottom line is, that this eventually will result in the error message:
! No room for a new \write .
\ch@ck ...\else \errmessage {No room for a new #3}
\fi
There is an additional disadvantage of immediately opening a new write handle for every
table of contents, list of figures, list of tables etc. These are not only set by the corresponding
commands, they also could not be set once more, because their helper files are empty after
the corresponding commands until the end of the document.
Package scrwfile provides an amendment of the L
A
TEX kernel, that solves both problems.
14.1. General Modifications of the L
A
TEX Kernel
To allocate a new file handle eg. for \listoffigures or \listoftables L
A
TEX classes use the
L
A
TEX kernel command \@starttoc. This command not only inputs the associated helper file
but also allocates a new write handle for the associated helper file and opens it for writing. Nev-
ertheless, if afterwards new entries to these lists of floats are added using \addcontentsline,
then these file handles are not used immediately, instead L
A
TEX writes \@writefile com-
mands into the aux-file. Only while reading the aux-file while the end of the document, those
\@writefile
commands become real write operations on the helper files. Additionally L
A
TEX
does not close the helper files explicitly. Instead L
A
TEX relies on TEX to close all open files at
the end.
Thus all the helper files are open throughout the entire process. However the content
is written at \end{document}. The basic idea of scrwfile is tackling this contradiction by
redefining \@starttoc and \@writefile.
Surely, changes of the L
A
TEX kernel may result in incompatibilities with other packages. In
case of scrwfile, clashes my arise with all packages also redefining \@starttoc or \@writefile.
Sometimes changing the order of loading the packages may help.
However, only few such problems have been reported eventhough several users have tested
the package for one year before its first release. See
section 14.5
for more information about
known incompatibilities. If you find such a problem, please contact the KOMA-Script author.
Chapter 14: Economise and Replace Files Using scrwfile
343
14.2. The Single File Feature
At the point the package is loaded using, e. g.,
\usepackage{scrwfile}
scrwfile will redefine \@starttoc to not longer allocate a write handle or open any file for writ-
ing. Immediately before closing the aux-file in \end{document} it will redefine \@writefile
to no longer write into the usual helper files but into one single new file with file extension
wrt
. After reading the aux-file this wrt-file will be processed once per helper file. This means,
that not all of the helper file have to be open at the same time, but only one at a time. And
this single file will be closed afterwards and the write handle is not longer needed after it is
closed. An internal write handle of L
A
TEX is used for this. So scrwfile doesn’t need any own
write handle.
Because of this, even if only one table of contents should be generated, loading scrwfile gives
one extra write file handle, e. g., for bibliographies, indexes, glossaries and similar, that are
not using \@starttoc. Additionally the number of tables of contents and lists of whatever,
that use \@starttoc is not limited any longer.
14.3. The Clone File Write Feature
Sometimes it is useful to input a file not only once but several times. As \@starttoc does not
open files for writing any more, this can be done by simply using \@starttoc several times
with the same extension. But sometimes you may have additional entries in only some of the
content directories. scrwfile allows to copy all entries of a file to another file, too. We call this
cloning.
\TOCclone[ heading ]{ source }{ destination }
activates the clone feature for files with extensions source and destination . All entries to
the file \jobname.source will be added to \jobname.destination .
If extension destination is a new one, destination will be added to the list of known
extensions using the KOMA-Script package tocbasic.
If the optional argument heading is given, a new list-of macro \listofdestination is
defined. heading will be used as section (or chapter) heading of this list. In this case several
tocbasic features of the source will be copied to destination , if and only if they have been
set up when \TOCclone was used. Feature nobabel will always be set, because the language
selection commands are part of the helper file and would be cloned, anyway.
Dostları ilə paylaş: |