From 40af42087ad5180e7ef930675b5eefa5e86f1363 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 21 Dec 2020 22:19:11 +0000 Subject: easyfloats (21dec20) git-svn-id: svn://tug.org/texlive/trunk@57195 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/latex/easyfloats/easyfloats.dtx | 1897 ++++++++++++++++++++ .../source/latex/easyfloats/easyfloats.ins | 82 + 2 files changed, 1979 insertions(+) create mode 100644 Master/texmf-dist/source/latex/easyfloats/easyfloats.dtx create mode 100644 Master/texmf-dist/source/latex/easyfloats/easyfloats.ins (limited to 'Master/texmf-dist/source/latex/easyfloats') diff --git a/Master/texmf-dist/source/latex/easyfloats/easyfloats.dtx b/Master/texmf-dist/source/latex/easyfloats/easyfloats.dtx new file mode 100644 index 00000000000..eea9932e40c --- /dev/null +++ b/Master/texmf-dist/source/latex/easyfloats/easyfloats.dtx @@ -0,0 +1,1897 @@ +% easyfloats.dtx +% Copyright 2020 E. Zöllner +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3 +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of LaTeX +% version 2005/12/01 or later. +% +% This work has the LPPL maintenance status `maintained'. +% +% The Current Maintainer of this work is E. Zöllner. +% +% This work consists of the files listed in easyfloats-file-list.txt. +% The official git repository is https://gitlab.com/erzo/latex-easyfloats + + +% dtx files (documented tex files) allow "to put the user documentation, +% code documentation and code itself in one place." +% https://www.texdev.net/2009/10/05/the-dtx-format/ +% see also +% https://www.texdev.net/2009/10/06/a-model-dtx-file/ +% https://ctan.org/pkg/dtxtut +% +% This file is a lot simpler, it contains nothing but the package code with comments. +% Technically it could be used instead of the sty file. +% easyfloats.ins reads this file, strips comments and indentation using docstrip +% and writes the result to the sty file in order to make it faster. + + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{easyfloats}[2020/12/20 v1.0.0] + + +% ========== options ========== + +% load either graphicx or graphbox +\newif\ifesf@loadgraphics +% load graphbox +\newif\ifesf@loadgraphbox +% load longtable +\newif\ifesf@loadlongtable +% load array +\newif\ifesf@loadarray +% load booktabs +\newif\ifesf@loadbooktabs +% print a warning if figure or table is used directly +\newif\ifesf@warnstandardfloats +\esf@warnstandardfloatstrue + +\DeclareOption{graphicx}{% + \esf@loadgraphicstrue + \esf@loadgraphboxfalse +} +\DeclareOption{graphbox}{% + \esf@loadgraphicstrue + \esf@loadgraphboxtrue +} +\DeclareOption{nographic}{% + \esf@loadgraphicsfalse + \esf@loadgraphboxfalse +} + +\DeclareOption{longtable}{% + \esf@loadlongtabletrue +} +\DeclareOption{nolongtable}{% + \esf@loadlongtablefalse +} + +\DeclareOption{booktabs}{% + \esf@loadbooktabstrue +} +\DeclareOption{nobooktabs}{% + \esf@loadbooktabsfalse +} + +\DeclareOption{array}{% + \esf@loadarraytrue +} +\DeclareOption{noarray}{% + \esf@loadarrayfalse +} + +% If I spell this with spaces LaTeX complains: +% > Unknown option `allowstandardfloats' +% It seems spaces are ignored by \usepackage +% but not by \DeclareOption. +% clsguide says: +% > Note that the name of an option should contain +% > only those characters allowed in a ‘LaTeX name’ +% So maybe it's better to not rely on that behaviour. +\DeclareOption{allowstandardfloats}{% + \esf@warnstandardfloatsfalse +} + +%\DeclareOption*{\objectset{\CurrentOption}} + + +\ExecuteOptions{graphicx, array, booktabs} + +% \relax is in definition order, starred is in specification order +\ProcessOptions\relax + + +% ========== required packages ========== + +\RequirePackage{etoolbox} +\RequirePackage{pgfkeys} + +% The float package defines the placement option H so that I don't need to +% provide a separate inline/floating option and deal with spacing and captions +% of inline objects. I can just use the usual environments like always. +% It also defines float styles which move the caption to the top or bottom of +% the object. It makes things easier for me because I can just insert the +% caption somewhere independent of the object type. +% I am *not* making use of it's capability to define new float types. +% Please note that \floatplacement is overridden if the placement option is non-empty. +\RequirePackage{float} + +% By default there is no space between a table and it's caption (at least with +% the standard document classes). The caption package fixes this. +% The caption package defines the \phantomcaption command (see object environment). +% The caption package is required by the subcaption package. +% It also gives the possibility to customize the layout of captions. But I am +% leaving it to the user to do this if desired. +\RequirePackage{caption} + +% subobjects +\RequirePackage{environ} + +% "Die Pakete subfigure.sty und subfig.sty werden nicht mehr weiterentwickelt +% und sind inkompatibel zu einigen aktuelleren Paketen wie hyperref.sty. +% Als Ersatz bei Kompatibilitätsproblemen empfiehlt sich subcaption.sty." +% (l2tabu, Version 2.4 vom 3. Februar 2016, Seite 16) +\RequirePackage{subcaption} + +% \includegraphics +\ifesf@loadgraphics + \ifesf@loadgraphbox + % extension for graphicx + \RequirePackage{graphbox} + \else + \RequirePackage{graphicx} + \fi +\fi + +% Set long tables which are not floating +% but can span across page breaks. +% Requires several runs. +\ifesf@loadlongtable + \RequirePackage{longtable} +\fi + +% Additional features in column specification like <, >, !. +% Changes also the behaviour of rules but that is irrelevant if you use booktabs. +\ifesf@loadarray + \RequirePackage{array} +\fi + +% Macros for formating tables. +\ifesf@loadbooktabs + \RequirePackage{booktabs} +\fi + + +% ========== init ========== + +\newif\ifobject@directkeys +\object@directkeystrue + +\newif\if@inobject +\newif\if@firstsubobject +\newif\if@containssubobjects + +\floatstyle{plaintop} +\restylefloat{table} +\floatstyle{plain} +\restylefloat{figure} + + +% ========== hooks ========== + +\newif\ifobject@isgraphic + +\newcommand{\object@hook}{} +\newcommand{\subobject@hook}{} +\newcommand{\object@graphic@hook}{} + +\newrobustcmd{\AtBeginObject}[1]{\appto\object@hook{#1}} +\newrobustcmd{\AtBeginSubobject}[1]{\appto\subobject@hook{#1}} +\newrobustcmd{\AtBeginGraphicObject}[1]{\appto\object@graphic@hook{#1}} + + +% ========== key management ========== + +\newcommand{\esf@ifpgfkeyhasvalue}[1]{% #1: key, #2: executed if #1 is set, #3: executed if #1 has not been set + % WARNING: Trying to get the value defines the key to \relax if it + % was undefined (because of \csname). Setting the key to \relax is + % discouraged because it causes inconsistent behaviour [TikZ & PGF + % Manual v3.1.5b page 976 \pgfkeysifdefined]. + % With eTeX: \pgfkeysifdefined will report the key as *defined*. + % Without eTeX: \pgfkeysifdefined will report the key as *un*defined. + % Therefore don't use this macro with undefined keys. If you do use + % it with an undefined key it will be treated as if it has been set [!]. + \pgfkeysgetvalue{#1}{\esf@tmp@value}% + \ifx \pgfkeysnovalue@text \esf@tmp@value + \expandafter \@secondoftwo + \else + \expandafter \@firstoftwo + \fi +} + +\newcommand{\esf@ifpgfkeyexists}[3]{% + % I cannot use \@firstoftwo and \@secondoftwo because \pgfkeysifdefined + % does not close the if statement before expanding the 2nd and 3rd argument + \pgfkeysifdefined{#1} + {#2} + {\pgfkeysifdefined{#1/.@cmd}{#2}{#3}}% +} +\newcommand{\esf@ifpgfkeyrequiresvalue}[3]{% #1: key, #2: then block, #3: else block + \pgfkeysifdefined{#1/.@def}{% + \pgfkeysgetvalue{#1/.@def}{\esf@tmp@value}% + \ifx \esf@tmp@value \pgfkeysvaluerequired + #2% + \else + #3% + \fi + }{% + #3% + }% +} + +\newcommand{\esf@ifkeyvalkeyexists}[4]{% #1: family, #2: key, #3: then block, #4: else block + % \ifcsdef would treat \relax as defined, \ifcsundef does not + \ifcsundef{KV@#1@#2}{#4}{#3}% +} +\newcommand{\esf@ifkeyvalkeyrequiresvalue}[2]{% #1: family, #2: key, #3: then block, #4: else block + % \ifcsdef would treat \relax as defined, \ifcsundef does not + \ifcsundef{KV@#1@#2@default}% +} + +\newcommand{\esf@pgfkeyscopyvalue}[2]{% #1: key to be set, #2 key to take the value from + % WARNING: the order of arguments is opposite of the shell command cp + % because all pgf macros take the key they operate on as first argument. + \pgfkeysgetvalue{#2}{\esf@tmp@value}% + \pgfkeyslet{#1}{\esf@tmp@value}% +} +\newcommand{\esf@pgfkeysvalueappend}[2]{% #1: key to be set, #2 value to be appended + \pgfkeysgetvalue{#1}{\esf@tmp@value}% + \appto\esf@tmp@value{#2}% + \pgfkeyslet{#1}{\esf@tmp@value}% +} + +\pgfqkeys{/handlers}{% + % ------- recommended ------- + .esf@recommended/.code={% + \esf@ifpgfkeyhasvalue{\pgfkeyscurrentpath}{% + % do nothing + }{% + \edef\esf@tmp@path{\pgfkeyscurrentpath}% + \PackageWarning{easyfloats}{Recommended key '\strippath\esf@tmp@path' not given. #1\ifx\pgfkeysnovalue#1\@empty\else. \fi This warning occured}% + }% + }, + % + % ------- mandatory ------- + .esf@mandatory/.code={% + \esf@ifpgfkeyhasvalue{\pgfkeyscurrentpath}{% + % do nothing + }{% + \edef\esf@tmp@path{\pgfkeyscurrentpath}% + \PackageError{easyfloats}{Mandatory key '\strippath\esf@tmp@path' not given\ifx\pgfkeysnovalue#1\@empty\else. \fi #1}{}% + }% + }, + % + % + % ------- save unknown ------- + % I can't use /pgf/keyfilters/defined with /pgf/key filter handlers/append filtered to + % because that appends full keys which are incompatible with keyval. + .esf@exec on unknown/.code={% #1: control sequence taking two args: key and value + \pgfkeysalso{\pgfkeyscurrentpath/.unknown/.code=% ##1: value + #1{\pgfkeyscurrentname}{##1}% + }% + }, + % + % ------- also from ------- + .esf@also from/.code={% #1: expandable control sequence containing options + \pgfkeysalsofrom{#1}% + }, + % + % ------- debugging ------- + .show boolean/.code={% + \begingroup + \renewcommand\pgfkeys@handle@boolean[2]{% ##1: if name, ##2: value + \expandafter \show \csname if##1\endcsname + }% + \edef\esf@tmp@path{\pgfkeyscurrentpath}% + \pgfkeysalso{\esf@tmp@path}% + \endgroup + }, + .show boolean/.value forbidden, +} + +\newcommand{\AppendToOptionsList}[3]{% #1: macro to append to, #2: key, #3: value + \ifdefvoid#1% + {}% + {\appto#1{, }}% + \eappto#1{#2}% + \ifx \pgfkeysnovalue #3\relax + % do nothing + \else + \appto#1{={#3}}% + \fi +} + +\newcommand{\strippath}[1]{% + \expandafter\strippath@do#1/\pgfeov +} +\def\strippath@do#1/#2\pgfeov{% + \if\relax\detokenize{#2}\relax + #1% + \else + \strippath@do#2\pgfeov + \fi +} + + +% ========== other helper ========== + +\newcommand{\IfEnvironmentExistsOrIsEmpty}[1]{% #1: environment name, #2: then block, #3: else block + \ifstrempty{#1}{% + \let\IfEnvironmentExistsOrIsEmpty@do=\@firstoftwo + }{\IfEnvironmentExists{#1}{% + \let\IfEnvironmentExistsOrIsEmpty@do=\@firstoftwo + }{% + \let\IfEnvironmentExistsOrIsEmpty@do=\@secondoftwo + }}% + \IfEnvironmentExistsOrIsEmpty@do +} + +\newcommand{\IfEnvironmentExists}[3]{% #1: environment name, #2: then block, #3: else block + \ifcsmacro{#1}{% + % I am not checking the existence of end#1 because for tabularx that is \relax. + #2% + }{% + #3% + }% +} + + +% \patchcmd replaces the first occurence only. +% therefore I am recursing as long as patching was successful +% to make sure that each occurrence was replaced. +% it is important to replace with \textunderscore instead of \_ +% because otherwise it would replace \_ by \\_ and loop infinitely. +\newcommand{\PatchUnderscore}[1]{% #1: macro + \patchcmd{#1} + {_}{\textunderscore} + {\PatchUnderscore#1}{}% +} + + +% ========== object ========== + +\newif\ifobject@warnotherenv +\newif\ifobject@warnnolabel +\newif\ifobject@warnnocaption +\newif\ifobject@showenv + +% ---------- set object options ---------- + +\newrobustcmd{\objectset}{% #1: options + \@ifnextchar [%] + \objectset@appendtostyles + \objectset@direct +} + +\newcommand{\objectset@direct}{% #1: options + \pgfqkeys{/object}% +} + +\newcommand{\GobbleLeadingSpaceIn}[1]{\edef#1{\expandafter\@firstofone#1}} + +\def\objectset@appendtostyles[#1]#2{% #1: style #2: options + \pgfkeyssetvalue{/object.check/env}{}% + \pgfqkeys{/object.check}{% + .esf@exec on unknown=\AppendOptionToObjectStyleGroups{#1}, + #2% + }% +} + +% ---------- check object options ---------- + +\newcommand{\CheckObjectOption}[2]{% #1: key, #2: value, #3: executed if valid + % if #3 is *not* executed an error message is printed + % + % It is important to reset it at the beginning + % because the \Check* macros do not expand any + % of the two arguments if they throw an error. + \let\CheckObjectOption@handleArg=\@gobble + \esf@ifpgfkeyexists{/object/#1}{% + \esf@ifpgfkeyrequiresvalue{/object/#1}{% + \ifx \pgfkeysnovalue #2\relax + \PackageError{easyfloats}{The key '#1' requires a value. I am going to ignore this key}{}% + \else + \let\CheckObjectOption@handleArg=\@firstofone + \fi + }{% + \let\CheckObjectOption@handleArg=\@firstofone + }% + }{\CheckObjectGraphicOption{#1}{#2}{% + \let\CheckObjectOption@handleArg=\@firstofone + }{\CheckObjectEnvArgs{#1}{#2}{% + \let\CheckObjectOption@handleArg=\@firstofone + }{% + \PackageError{easyfloats}{I do not know the key '#1' and I am going to ignore it. Perhaps you misspelled it}{}% + }}}% + \CheckObjectOption@handleArg +} + + +% ---------- available object options ---------- + +\pgfqkeys{/object}{% + % + % ------- mandatory ------- + % + % The environment to use (figure|table) + % An empty value is allowed for longtable + % but that is intentionally left undocumented. + type/.initial, + type/.value required, + type/.code=\@ifundefined{fps@#1} + {\PackageError{easyfloats}{Invalid value for key 'type': '#1'. I am going to ignore this option}{}} + {\pgfkeyssetvalue{/object/type}{#1}}, + % + % Where to place the caption, see float package (plain|plaintop|ruled|boxed) + % If empty do *not* perform a restyle. + % This is ignored if type is empty. + float style/.initial=, + float style/.value required, + % + % + % ------- recommended ------- + % + % The caption displayed above or below the content (depending on the float style). + % There is *no* dot added automatically behind it. + caption/.initial, + caption/.value required, + caption/.prefix code={% + \esf@ifpgfkeyhasvalue{/object/caption}{% + \PackageWarning{easyfloats}{Overwriting existing value for caption with "#1"}% + }{% + % ok + }% + }, + % + % A label which can be referenced by e.g. \ref{label} or \refpage{label} + label/.initial, + label/.value required, + label/.prefix code={% + \esf@ifpgfkeyhasvalue{/object/label}{% + \PackageWarning{easyfloats}{Overwriting existing value for label with "#1"}% + }{% + % ok + }% + }, + % + % + % ------- optional ------- + % + % Where to put the float on the page ([htbp]+ | H | ) + % (empty means to *not* pass the optional placement argument to the foating environment) + % This is more powerful than \floatplacement because it allows H. + placement/.initial=, + placement/.value required, + % + % The caption used in the list of figures/list of tables + list caption/.initial, + list caption/.value required, + % + % An addition to the caption (at the object only, not in a list) + details/.initial=, + details/.value required, + % + details sep/.initial=.\space, + details sep/.value required, + % + % An additional label which can be used synonymously to label. + % If this key is given several times, only the last one will have an effect. + add label/.initial, + add label/.value required, + % + % TeX code which is inserted at the beginning of the type environment + align/.initial=\centering, + align/.value required, + % + % TeX code which is inserted at the beginning of the type environment (before align) + exec/.initial=, + exec/.value required, + exec +/.code=\esf@pgfkeysvalueappend{/object/exec}{#1}, + exec +/.value required, + exec+/.forward to=/object/exec +, + exec+/.value required, + % + % An additional inner environment to wrap the content in like tabular, tabularx, tikzpicture + env/.code=\IfEnvironmentExistsOrIsEmpty{#1} + {\pgfkeyssetvalue{/object/env}{#1}}% + {\PackageError{easyfloats}{Environment #1 which you passed to the key 'env' does not exist}{}}, + env/.value required, + env=, + % + % Specify that this object contains subobjects. + % This means that if env has a non-empty value + % this value is used for subobject env + % and env is set to an empty value. + sub/.forward to=/object/contains subobjects, + contains subobjects/.is if = @containssubobjects, + % + % + % ------- tables ------- + % first head and last foot are optional but if they are given they have priority. + % head and foot always need to have a value even if it's just empty. + % + first head/.initial, + first head/.value required, + % + head/.initial=, + head/.value required, + % + foot/.initial=, + foot/.value required, + % + last foot/.initial, + last foot/.value required, + % + table head style/.code=\pgfkeysdef{/object/table head}{\pgfqkeys{/object}{#1}}, + table head style/.value required, + table head style={% + first head = + \toprule + #1 \\ + \midrule, + head = + #1 \\ + \midrule, + foot = + \midrule + \ifx\object@tableBreakText\@empty + \else + \multicolumn{\the\LT@cols}{r@\relax}{\object@tableBreakText}% + \fi, + last foot = + \bottomrule, + }, + % + % text displayed in the non-last foot of a table + table break text/.code=\def\object@tableBreakText{#1}, + table break text/.value required, + table break text = (to be continued), + % + % + % ------- warnings ------- + % + warn no caption/.is if=object@warnnocaption, + warn no caption=true, + % + warn no label/.is if=object@warnnolabel, + warn no label=true, + % + warn other env/.is if=object@warnotherenv, + warn other env=false, + % + % + % ------- debugging ------- + % + show env args/.is if=object@showenv, + show env args=false, + % + % + % ------- subobject ------- + % .value required is code duplication but + % it is necessary for \esf@ifpgfkeyrequiresvalue. + % It also changes the error message to report + % this key instead of the linked key. + % + subobject linewidth/.forward to=/subobject/linewidth, + subobject linewidth/.value required, + subobject env/.forward to=/subobject/env, + subobject env/.value required, + % + subcaptionbox/.forward to=/subobject/subcaptionbox, + subcaptionbox/.value forbidden, + subpage/.forward to=/subobject/subpage, + subpage/.value forbidden, + % + subcaptionbox inner pos/.forward to=/subobject/subcaptionbox inner pos, + subcaptionbox inner pos/.value required, + % + subpage inner pos/.forward to=/subobject/subpage inner pos, + subpage inner pos/.value required, + subpage height/.forward to=/subobject/subpage height, + subpage height/.value required, + subpage outer pos/.forward to=/subobject/subpage outer pos, + subpage outer pos/.value required, + subpage align/.forward to=/subobject/subpage align, + subpage align/.value required, + % + subobject sep/.forward to=/subobject/sep, + subobject sep/.value required, + % + subobject hor/.forward to=/subobject/hor, + %subobject hor/ value is allowed but not necessary + subobject hor sep/.forward to=/subobject/hor sep, + subobject hor sep/.value required, + subobject hor sep+/.forward to=/subobject/hor sep+, + subobject hor sep+/.value required, + subobject hor sep +/.forward to=/subobject/hor sep +, + subobject hor sep +/.value required, + % + subobject ver/.forward to=/subobject/ver, + %subobject ver/ value is allowed but not necessary + subobject ver sep/.forward to=/subobject/ver sep, + subobject ver sep/.value required, + subobject ver sep+/.forward to=/subobject/ver sep+, + subobject ver sep+/.value required, + subobject ver sep +/.forward to=/subobject/ver sep +, + subobject ver sep +/.value required, + % + subobject exec/.forward to=/subobject/exec, + subobject exec/.value required, + subobject exec+/.forward to=/subobject/exec+, + subobject exec+/.value required, + subobject exec +/.forward to=/subobject/exec +, + subobject exec +/.value required, + % + subobject warn no caption/.forward to=/subobject/warn no caption, + %value is allowed but not necessary + subobject warn no label/.forward to=/subobject/warn no label, + %value is allowed but not necessary + % + % + % ------- unknown handler / key patterns ------- + % + % Two key patterns are defined to automatically pass arguments to the environments specified by the env option if the environment name matches. + % ` arg` is for a single mandatory (undelimited) argument. It is wrapped in braces. + % ` args` is not wrapped in braces and can be used for several arguments or an optional argument. + % It cannot be used for a single mandatory argument because \pgfkeys strips several levels of braces. + .unknown/.code={% + \ObjectProcessKeyPattern{\pgfkeyscurrentname}{#1}{% + \pgfkeysgetvalue{/object/.really unknown/.@cmd}{\esf@tmp@err}% + \esf@tmp@err#1\pgfeov + }% + }, + % Setting an unknown key handler shall not override env args but set an additional unknown handler. + .unknown/.code/.code={% + \pgfkeysdef{/object/.really unknown}{#1}% + }, + .really unknown/.code={% + \edef\do{\noexpand\pgfkeys{/errors/unknown key={\pgfkeyscurrentkey}{\unexpanded{#1}}}}% + \do + }, +} + +\pgfqkeys{/object.check}{% + env/.initial=, + env/.code={% + \ifx \pgfkeysnovalue #1\relax + \PackageError{easyfloats}{The key 'env' requires a value. I am going to ignore this key}{}% + \else + \IfEnvironmentExistsOrIsEmpty{#1}{% + % set env so that I can use the value to check args + \pgfkeyssetvalue{/object.check/env}{#1}% + % call the unknown handler which appends it to the style + % unlike '/errors/unknown key' '.unknown' does not take the key as argument + % but it may require \pgfkeyscurrentpath and \pgfkeyscurrentname to be set + \pgfkeys@split@path + \pgfkeysvalueof{\pgfkeyscurrentpath/.unknown/.@cmd}#1\pgfeov + }{% + \PackageError{easyfloats}{Environment #1 which you passed to the key 'env' does not exist}{}% + }% + \fi + }, + type/.code={% + % set type so that I can use the value in \NewObjectStyleGroup + \pgfkeyssetvalue{/object.check/type}{#1}% + % call the unknown handler which appends it to the style + % unlike '/errors/unknown key' '.unknown' does not take the key as argument + % but it may require \pgfkeyscurrentpath and \pgfkeyscurrentname to be set + \pgfkeys@split@path + % Without the braces I got "Undefined control sequence. [...] \pgfeov" + % \pgfkeys strips several levels of braces around an argument. + % (I have already experienced that while experimenting with args. + % That is the reason why I defined two separate keys arg and args.) + % I am assuming that because of that the \pgfeov ended the argument of some + % pgfkeys internal macro too early causing undefined behavior. + % I am preventing this from happening by hiding \pgfeov inside of braces + % which are inside of the argument so they won't get stripped. + % I put \@firstofone in front of them so that they do not function as a group. + \@firstofone{\pgfkeysvalueof{\pgfkeyscurrentpath/.unknown/.@cmd}#1\pgfeov}% + }, +} + +% ---------- process key patterns ---------- + +\newcommand{\ObjectProcessKeyPattern}[2]{% #1: key, #2: value, #3: else + \expandafter\ObjectProcessKeyPattern@expandedkey\expandafter{#1}{#2}% +} + +\newcommand{\ObjectProcessKeyPattern@expandedkey}[2]{% #1: key, #2: value, #3: else + \ObjectProcessGraphicOption@expandedkey{#1}{#2}{% + \@gobble + }{% + \ObjectProcessArgs@expandedkey{#1}{#2}\relax + }% +} + +% ---------- process graphic options ---------- + +\ifesf@loadgraphics + +% do not confuse this with \CheckGraphicobjectOption +\newcommand{\CheckObjectGraphicOption}[2]{% #1: key, #2: value + % #3: executed if valid, #4: executed if *not* a graphic option + % Please note that if the option looks like a graphic option + % but is not valid neither #3 nor #4 is executed. + % Instead an appropriate error message is printed. + \begingroup + \let\ObjectCheckGraphicOption@aftergroup=\@gobbletwo + \renewcommand{\AppendToOptionsList}[3]{% + \let\ObjectCheckGraphicOption@aftergroup=\@firstoftwo + }% + \ObjectProcessGraphicOption{#1}{#2}{% + \let\ObjectCheckGraphicOption@aftergroup=\@secondoftwo + }% + \expandafter + \endgroup + \ObjectCheckGraphicOption@aftergroup +} + +\newcommand{\ObjectProcessGraphicOption}[2]{% #1: key, #2: value + % #3: executed if *not* a graphic option + \expandafter\ObjectProcessGraphicOption@expandedkey\expandafter{#1}{#2}\relax +} +\newcommand{\ObjectProcessGraphicOption@expandedkey}[2]{% #1: key, #2: value + % #3: executed if graphic option, #4: executed if *not* a graphic option + \ObjectProcessGraphicOption@checkoption#1graphic \pgfeov{#2}% +} +\long\def\ObjectProcessGraphicOption@checkoption#1graphic #2\pgfeov#3{% #1: empty if graphic option, #2: key, #3: value + % #4: executed if graphic option, #5: executed if *not* a graphic option + \def\esf@tmp@arg{#1}% + \ifx \esf@tmp@arg \@empty + \edef\esf@opgoco@key{\StripGraphicSpace#2\pgfeov}% + \CheckGraphicobjectOption{\esf@opgoco@key}{#3}{% + \AppendGraphicobjectOption{\esf@opgoco@key}{#3}% + }% + \expandafter \@firstoftwo + \else + \expandafter \@secondoftwo + \fi +} + +\def\StripGraphicSpace#1graphic \pgfeov{#1} + +\else %\ifesf@loadgraphics + +\newcommand{\CheckObjectGraphicOption}[2]{% #1: key, #2: value + % #3: executed if valid, #4: executed if *not* a graphic option + \@secondoftwo +} + +\newcommand{\ObjectProcessGraphicOption@expandedkey}[2]{% #1: key, #2: value + % #3: executed if graphic option, #4: executed if *not* a graphic option + \@secondoftwo +} + +\fi %\ifesf@loadgraphics + +% ---------- process env args ---------- + +\newcommand{\@object@envkey}{/object/env} +\newcommand{\CheckObjectEnvArgs}[2]{% #1: key, #2: value + % #3: executed if valid, #4: executed if *not* an arg + % Please note that if the option looks like an arg + % but is not valid neither #3 nor #4 is executed. + % Instead an appropriate error message is printed. + \begingroup + \edef\ObjectCheckArgs@key{#1}% + \let\ObjectCheckArgs@aftergroup=\@gobbletwo + \pgfkeysgetvalue{/object.check/env}{\esf@tmp@env}% + \pgfkeys{\@object@envkey/.expand once=\esf@tmp@env}% + \renewcommand{\ObjectDefineEnvargs}[2]{% ##1: env name, ##2: arguments + \let\ObjectCheckArgs@aftergroup=\@firstoftwo + }% + \ObjectProcessArgs{\ObjectCheckArgs@key}{#2}{% + \let\ObjectCheckArgs@aftergroup=\@secondoftwo + }% + \expandafter + \endgroup + \ObjectCheckArgs@aftergroup +} + + +\newcommand{\ObjectProcessArgs}[2]{% #1: key, #2: value, #3: else + \expandafter\ObjectProcessArgs@expandedkey\expandafter{#1}{#2}\relax +} + +\newcommand{\ObjectProcessArgs@expandedkey}[2]{% #1: key, #2: value, #3: then, #4: else + \IfEndsOnSpacePlus{#1}{% + \let\ObjectProcessArgs@csdef=\csappto + \expandafter\ObjectProcessArgs@checkArgs\expandafter{\StripSpacePlus#1\pgfeov}{#2}% + }{\IfEndsOnPlus{#1}{% + \let\ObjectProcessArgs@csdef=\csappto + \expandafter\ObjectProcessArgs@checkArgs\expandafter{\StripPlus#1\pgfeov}{#2}% + }{% + \let\ObjectProcessArgs@csdef=\csdef + \ObjectProcessArgs@checkArgs{#1}{#2}% + }}% +} + +\newrobustcmd{\IfEndsOn}[2]{% #1: end character, #2: text + \def\IfEndsOn@do##1#1##2\pgfeov{% + \ifstrequal{##2}{}{% + \let\do=\@secondoftwo + }{\ifstrequal{##2}{#1}{% + \let\do=\@firstoftwo + }{% + \def\do{\IfEndsOn@do##2\pgfeov}% + }}% + \do + }% + \IfEndsOn@do#2#1\pgfeov +} +\newcommand{\IfEndsOnPlus}{\IfEndsOn+} +\newcommand{\IfEndsOnSpacePlus}{\IfEndsOn{ +}} + +\def\StripSpacePlus#1 +\pgfeov{#1} +\def\StripPlus#1+\pgfeov{#1} + + +\newcommand{\ObjectProcessArgs@checkArgs}[2]{% #1: key, #2: value, #3: then, #4: else + \ObjectProcessArgs@do#1 args\pgfeov{#2}% +} +\long\def\ObjectProcessArgs@do#1 arg#2\pgfeov#3{% #1: env name, #2: test value, #3: arguments, #4: then, #5: else + \let\ObjectProcessArgs@do@after=\@firstoftwo + \ifstrequal{#2}{ args}{% + \ObjectDefineEnvargsCheckName{#1}{{#3}}% + }{\ifstrequal{#2}{s args}{% + \ObjectDefineEnvargsCheckName{#1}{#3}% + }{\ifstrequal{#2}{s}{% + \ifstrequal{#1}{arg}{% + \ObjectDefineEnvargsAuto{{#3}}% + }{\ifstrequal{#1}{args}{% + \ObjectDefineEnvargsAuto{#3}% + }{% + \let\ObjectProcessArgs@do@after=\@secondoftwo + }}% + }{% + \let\ObjectProcessArgs@do@after=\@secondoftwo + }}}% + \ObjectProcessArgs@do@after +} +\newcommand{\ObjectDefineEnvargsCheckName}[2]{% #1: env name, #2: arguments + \ifobject@directkeys + \pgfkeysgetvalue{\@object@envkey}{\esf@tmp@env}% + \ifdefvoid{\esf@tmp@env}{% + }{\ifdefstring{\esf@tmp@env}{#1}{% + }{% + \ifobject@warnotherenv + \PackageWarning{easyfloats}{Defining 'arg(s)' for #1 but 'env=\esf@tmp@env'}% + \fi + }}% + \fi + \IfEnvironmentExists{#1} + {\ObjectDefineEnvargs{#1}{#2}} + {\PackageError{easyfloats}{Environment #1 for which you set 'arg(s)' does not exist}{}}% +} +\newcommand{\ObjectDefineEnvargsAuto}[1]{% #1: arguments + \pgfkeysgetvalue{\@object@envkey}{\esf@tmp@env}% + \ifx \esf@tmp@env \@empty + \PackageError{easyfloats}{'env' for 'arg(s)' is not defined}{}% + \else + \ObjectDefineEnvargs{\esf@tmp@env}{#1}% + \fi +} +\newcommand{\ObjectDefineEnvargs}[2]{% #1: env name, #2: arguments + \ObjectProcessArgs@csdef{object@#1 env@args}{#2}% +} + + +\newcommand{\ObjectAppendEnvargs}[1]{% #1: macro + \ifcsname object@\pgfkeysvalueof{\@object@envkey} env@args\endcsname + \eappto#1{\csexpandonce{object@\pgfkeysvalueof{\@object@envkey} env@args}}% + \fi +} + + +% ---------- object environment ---------- + +\newcommand{\object@head}{} +\newcommand{\object@foot}{} +\newcommand{\object@restorestandardfloats}{} + +\newcommand{\object@label}[1]{% + \pgfkeys{/object/label={#1}}% +}% +\newcommand{\object@caption}[2][\pgfkeysnovalue]{% + \pgfkeys{/object/caption={#2}}% + \ifx \pgfkeysnovalue #1\relax + \pgfkeys{/object/list caption={#2}}% + \else + \pgfkeys{/object/list caption={#1}}% + \fi +} +\newcommand{\object@longtable@label}[1]{% + \ObjectDefineEnvargs{longtable}{\label{#1}}% +}% +\newcommand{\object@longtable@caption}[2][\pgfkeysnovalue]{% + \ifx \pgfkeysnovalue #1\relax + \ObjectDefineEnvargs{longtable}{\caption{#2}}% + \else + \ObjectDefineEnvargs{longtable}{\caption[#1]{#2}}% + \fi + \def\object@longtable@caption@sep{\ObjectDefineEnvargs{longtable}{\\}}% +} + +\newenvironment{object}[1]{% #1: options + \if@inobject + \PackageError{easyfloats}{object environment may not be nested}{Did you mean to use the subobject environment instead?}% + \fi + \@inobjecttrue + % + \object@restorestandardfloats + % + \object@hook + \ifobject@isgraphic + \object@graphic@hook + \global\object@isgraphicfalse + \fi + % + % ---------- options --------- + % + \pgfqkeys{/object}{% + #1, + % + % ------- mandatory ------- + type/.esf@mandatory=It should be the name of a floating environment like figure or table, + float style/.esf@mandatory={It should be one of plain, plaintop, ruled or boxed. See float package}, + env/.esf@mandatory=It should be the name of an environment like tabular or empty, + }% + % + % ------- contains subobjects ------- + \if@containssubobjects + \pgfkeysgetvalue{/object/env}{\esf@tmp@env}% + \ifx \esf@tmp@env \@empty + \else + \pgfkeys{/subobject/env/.expand once=\esf@tmp@env}% + \pgfkeyssetvalue{/object/env}{}% + \fi + \fi + % + % ---------- prepare --------- + % + \pgfkeysgetvalue{/object/env}{\esf@tmp@env}% + \ifdefstring\esf@tmp@env{longtable}{% + \object@longtable@prepare + }{% + \esf@ifpgfkeyhasvalue{/object/first head}{% + \pgfkeysgetvalue{/object/first head}{\object@head}% + }{% + \pgfkeysgetvalue{/object/head}{\object@head}% + }% + \esf@ifpgfkeyhasvalue{/object/last foot}{% + \pgfkeysgetvalue{/object/last foot}{\object@foot}% + }{% + \pgfkeysgetvalue{/object/foot}{\object@foot}% + }% + }% + % + \pgfkeysgetvalue{/object/type}{\esf@tmp@type}% + \ifx\esf@tmp@type\@empty + \let\object@floatenv@begin=\relax + \let\object@floatenv@end=\relax + \else + \pgfkeysgetvalue{/object/float style}{\esf@tmp@floatstyle}% + \ifx \esf@tmp@floatstyle \@empty + \else + \floatstyle{\esf@tmp@floatstyle}% + \restylefloat{\esf@tmp@type}% + \fi + \edef\object@floatenv@begin{\expandonce{\csname\esf@tmp@type\endcsname}}% + \edef\object@floatenv@end{\expandonce{\csname end\esf@tmp@type\endcsname}}% + \pgfkeysgetvalue{/object/placement}{\esf@tmp@placement}% + \ifx \esf@tmp@placement \@empty + % do nothing + \else + \eappto\object@floatenv@begin{[\esf@tmp@placement]}% + \fi + \fi + % + \pgfkeysgetvalue{/object/details}{\object@details}% + \ifx \object@details \@empty + % do nothing + \else + \preto\object@details{\pgfkeysvalueof{/object/details sep}}% + \fi + % + \pgfkeysgetvalue{/object/env}{\esf@tmp@env}% + \ifx \esf@tmp@env \@empty + % if you change this remember to update \object@lookahead@beforesubobject + \def\object@innerenv@begin{\object@head\ignorespaces}% + \def\object@innerenv@end{\unskip\object@foot}% + \else + \edef\object@innerenv@begin{\expandonce{\csname\esf@tmp@env\endcsname}}% + \edef\object@innerenv@end{\expandonce{\csname end\esf@tmp@env\endcsname}}% + \ObjectAppendEnvargs{\object@innerenv@begin}% + \eappto\object@innerenv@begin{\expandonce{\object@head}}% + \epreto\object@innerenv@end{\expandonce{\object@foot}}% + \let\object@lookahead@begin=\object@innerenv@begin + \ifobject@showenv + \show\object@innerenv@begin + \fi + \let\object@innerenv@begin=\object@lookahead + \fi + % + \global \@firstsubobjecttrue + % + % ---------- execute --------- + % + \object@floatenv@begin + \let\esf@original@label=\label + \let\esf@original@caption=\caption + \let\label=\object@label + \let\caption=\object@caption + \pgfkeysvalueof{/object/exec}% + \pgfkeysvalueof{/object/align}% + \object@innerenv@begin +}{% + \object@innerenv@end + \if@containssubobjects + \if@firstsubobject + \PackageWarning{easyfloats}{'contains subobjects' is true but the object does not contain any subobjects.}% + \fi + \fi + \let\label=\esf@original@label + \let\caption=\esf@original@caption + \object@processCaptionAndLabel + \object@floatenv@end +} + +\newcommand{\object@processCaptionAndLabel}{% + % position of caption (above/below) is handled by float package (see float style) + \esf@ifpgfkeyhasvalue{/object/caption}{% + \esf@ifpgfkeyhasvalue{/object/list caption}% + {\pgfkeysgetvalue{/object/list caption}{\esf@tmp@caption@short}}% + {\pgfkeysgetvalue{/object/caption}{\esf@tmp@caption@short}}% + \caption[\esf@tmp@caption@short]{\pgfkeysvalueof{/object/caption}\object@details}% + }{% + \ifobject@warnnocaption + \PackageWarning{easyfloats}{% + No caption given. + This object will not show up in the list of figures/tables/whatsoever. + If captions for subfigures are given they will be placed incorrectly in the list of figures. + If you are using hyperref links to this figure may turn out wrong. + This warning occured% + }% + \fi + % Generate an anchor for a \label. + % \phantomcaption is defined in the caption-package but + % documented in subcaption for the subfigure environment. + % It appears that here (without a subfigure but within a figure) + % references are output correctly but links created by hyperref + % which should be pointing to this object point to the previous caption. + \phantomcaption + }% + % ------- label ------- + \esf@ifpgfkeyhasvalue{/object/label}{% + \label{\pgfkeysvalueof{/object/label}}% + }{% + \ifobject@warnnolabel + \PackageWarning{easyfloats}{% + No label given. + Without a label you cannot reference this object. + This warning occured% + }% + \fi + }% + \esf@ifpgfkeyhasvalue{/object/add label}% + {\label{\pgfkeysvalueof{/object/add label}}}% + {}% +} + +\newcommand{\object@longtable@prepare}{% + \pgfkeyssetvalue{/object/type}{}% + \pgfkeyssetvalue{/object/align}{}% + \let\object@label=\label + \let\object@caption=\caption + \let\ObjectProcessArgs@csdef=\csappto + % + \let\esf@original@label=\label + \let\esf@original@caption=\caption + \let\label=\object@longtable@label + \let\caption=\object@longtable@caption + \let\object@longtable@caption@sep=\relax + % it seems possible to have a label without a caption in a longtable + % which actually makes sense because \caption may appear several times + % so it makes sense to increase the counter somewhere else. + \let\phantomcaption=\relax + \object@processCaptionAndLabel + \let\object@processCaptionAndLabel=\relax + \object@longtable@caption@sep + \let\label=\esf@original@label + \let\caption=\esf@original@caption + % + \esf@ifpgfkeyhasvalue{/object/first head}{% + \ObjectDefineEnvargs{longtable}{\pgfkeysvalueof{/object/first head}}% + }{% + \ObjectDefineEnvargs{longtable}{\pgfkeysvalueof{/object/head}}% + }% + \ObjectDefineEnvargs{longtable}{% + \endfirsthead + \pgfkeysvalueof{/object/head}% + \endhead + \pgfkeysvalueof{/object/foot}% + \endfoot + }% + \esf@ifpgfkeyhasvalue{/object/last foot}{% + \ObjectDefineEnvargs{longtable}{\pgfkeysvalueof{/object/last foot}}% + }{% + \ObjectDefineEnvargs{longtable}{\pgfkeysvalueof{/object/foot}}% + }% + \ObjectDefineEnvargs{longtable}{% + \endlastfoot + }% +} + + +% ---------- lookahead for subobjects ---------- + +\newcommand{\object@lookahead@nosubobject}{% + \object@lookahead@begin +} +\newcommand{\object@lookahead@beforesubobject}{% + \PackageWarning{easyfloats}{It seems you have forgotten to specify 'contains subobjects'. I am using the value of 'env' for the subobjects instead of for \@currenvir.}% + \pgfkeysgetvalue{/object/env}{\esf@tmp@env}% + \pgfkeys{/subobject/env/.expand once=\esf@tmp@env}% + \pgfkeyssetvalue{/object/env}{}% + \let\object@innerenv@end=\unskip + %\ignorespaces unnecessary because I just checked + %that the next token is the start of a subobject +} + +\newcommand{\object@lookahead}{% + \futurelet \next \object@lookahead@checknext +} +\newcommand{\object@lookahead@checknext}{% + \ifx \next \@implicitspace + \let\object@lookahead@gobble=\@gobblespace + \let\object@lookahead@do=\object@lookahead + \else\ifx \next \par + \let\object@lookahead@gobble=\@gobble + \let\object@lookahead@do=\object@lookahead + \else\ifx \next \begin + \let\object@lookahead@gobble=\@empty + \let\object@lookahead@do=\object@lookahead@checkbegin + \else\ifx \next \includegraphicsubobject + \let\object@lookahead@gobble=\@empty + \let\object@lookahead@do=\object@lookahead@beforesubobject + \else + \let\object@lookahead@gobble=\@empty + \let\object@lookahead@do=\object@lookahead@nosubobject + \fi \fi \fi \fi + \expandafter \object@lookahead@do \object@lookahead@gobble +} +\newcommand{\object@lookahead@checkbegin}[2]{% #1: \begin, #2: environment name + \ifstrequal{#2}{subobject} + \object@lookahead@beforesubobject + \object@lookahead@nosubobject + #1{#2}% +} + +\@firstofone{\let\@implicitspace= } +\@firstofone{\def\@gobblespace} {} + + +% ========== object styles ========== + +\newcommand{\IfObjectStyleExists}[1]{% #1: style name or group name, #2: then block, #3: else block + \ifcsmacro{object@style@#1}% +} +\newcommand{\IfObjectStyleNotGroup}[1]{% #1: style name, #2: then block, #3: else block + \IfObjectStyleExists{#1} + {\edef\esf@tmp@do{\ifcsstring{object@stylegroup@#1}{{#1}}}\esf@tmp@do}% + \@secondoftwo +} + +\newcommand{\objectstyle@init}[1]{% #1: style name or group name + \expandafter \newcommand \csname object@style@#1\endcsname{/utils/exec=\object@directkeysfalse}% + \expandafter \newcommand \csname object@stylegroup@#1\endcsname{}% +} + +\newrobustcmd{\AddObjectStyleToGroup}[2]{% #1: group name, #2: style name + \IfObjectStyleExists{#1}{% + \IfObjectStyleNotGroup{#2}{% + \AddObjectStyleToGroup@do{#1}{#2}% + }{% + \PackageError{easyfloats}{Undefined object style: #2}{In this case you cannot use a style group instead of a group.}% + }}{% + \PackageError{easyfloats}{Undefined object style group: #1}{}% + }% +} +\newrobustcmd{\AddObjectStyleToGroup@do}[2]{% #1: group name, #2: style name + \expandafter\eappto\csname object@stylegroup@#1\endcsname{{#2}}% +} +\newrobustcmd{\ShowObjectStylesInGroup}[1]{% + \expandafter\show\csname object@stylegroup@#1\endcsname +} + +\newcommand{\AppendOptionToObjectStyleGroups}[3]{% #1: list of style groups, #2: key, #3: value + \CheckObjectOption{#2}{#3}{% + \@for\esf@aotosg@group:=#1\do{% + \GobbleLeadingSpaceIn\esf@aotosg@group + \AppendOptionToObjectStyleGroup\esf@aotosg@group{#2}{#3}% + }% + }% +} +\newcommand{\AppendOptionToObjectStyleGroup}[3]{% #1: style group, #2: key, #3: value + \IfObjectStyleExists{#1}{% + \expandafter \let \expandafter \esf@tmp@listofstyles \csname object@stylegroup@#1\endcsname + \def\esf@tmp@loop{\@tfor\esf@aotosg@style:=}% + \expandafter\esf@tmp@loop\esf@tmp@listofstyles \do {% + \AppendOptionToObjectStyle\esf@aotosg@style{#2}{#3}% + }% + }{% + \PackageError{easyfloats}{Undefined object style: '#1'}{}% + }% +} +\newcommand{\AppendOptionToObjectStyle}[3]{% #1: style, #2: key, #3: value + \expandafter\AppendToOptionsList\csname object@style@#1\endcsname{#2}{#3}% +} +\newrobustcmd{\ShowObjectStyleOptions}[1]{% + \IfObjectStyleNotGroup{#1} + {\expandafter\show\csname object@style@#1\endcsname}% + {\PackageError{easyfloats}{Undefined object style: '#1'}{}}% +} + + +% ---------- style groups ---------- + +\newrobustcmd{\NewObjectStyleGroup}[2]{% #1: group name, #2: list of style names + \IfObjectStyleExists{#1}{% + \PackageError{easyfloats}{Style or style group with the name '#1' exists already}{}% + }{% + \objectstyle@init{#1}% + \@for\esf@nosg@style:=#2\do{% + \GobbleLeadingSpaceIn\esf@nosg@style + \AddObjectStyleToGroup{#1}{\esf@nosg@style}% + }% + }% +} + +% ---------- object styles ---------- + +\newrobustcmd{\NewObjectStyle}[2]{% #1: name, #2: options + \IfObjectStyleExists{#1}{% + \PackageError{easyfloats}{Style or style group with the name '#1' exists already}{}% + }{% + \objectstyle@init{#1}% + \AddObjectStyleToGroup@do{#1}{#1}% + %hack into \objectset[#1] to retrieve the value of type + \pgfkeyssetvalue{/object.check/type}{\pgfkeysnovalue}% + \objectset[#1]{#2}% + \esf@ifpgfkeyhasvalue{/object.check/type}{% + \edef\@do{\noexpand\DeprecateStandardFloatObject{\pgfkeysvalueof{/object.check/type}}{#1object}}% + \@do + }{% + \PackageError{easyfloats}{Missing required key 'type'}% + }% + % + \AddObjectStyleToGroup{all}{#1}% + % + \newenvironment{#1object}[1]{% #1: options + \object{% + .esf@also from/.expand once=\csname object@style@#1\endcsname, + /utils/exec=\object@directkeystrue, + ##1, + }% + }{% + \endobject + }% + \pgfkeysgetvalue{/object.check/type}{\NewObjectStyle@type}% + \edef\@do{\noexpand\AfterPreamble{% + \noexpand\IfEnvironmentExists{sub\NewObjectStyle@type}{% + \noexpand\PackageInfo{easyfloats}{environment 'sub\NewObjectStyle@type' exists already}% + }{\NewObjectStyle@IfCaptionNewEnough{% + \noexpand\PackageInfo{easyfloats}{declaring new caption subtype 'sub\NewObjectStyle@type'}% + \noexpand\DeclareCaptionSubType{\NewObjectStyle@type}% + }{% + \noexpand\PackageWarning{easyfloats}{The caption package is too old for me to define the subtype automatically. Please insert `\string\AtBeginDocument{\string\DeclareCaptionSubType{\NewObjectStyle@type}}' before loading this package}% + }% + }% + }}\@do + }% +} + +\@ifpackagelater{caption}{2020/08/30} + {\let\NewObjectStyle@IfCaptionNewEnough=\@firstoftwo} + {\let\NewObjectStyle@IfCaptionNewEnough=\@secondoftwo} + + +\newcommand{\DeprecateStandardFloatObject}[2]{% #1: float environment, #2: alternative object environment + \ifesf@warnstandardfloats + \ifcsmacro{esf@#1@alternatives}{% + \expandafter \appto \csname esf@#1@alternatives\endcsname{ or #2}% + }{% + \AtBeginDocument{% + \csletcs{esf@original#1}{#1}% + \expandafter \preto\csname#1\endcsname{\PackageWarning{easyfloats}{In order to profit from the advantages of the easyfloats package please use \csname esf@#1@alternatives\endcsname\space instead}}% + }% + \expandafter \def \csname esf@#1@alternatives\endcsname{#2}% + \ifesf@loadgraphics + \ifstrequal{#1}{table}{% + % do nothing + }{% + \expandafter \appto \csname esf@#1@alternatives\endcsname{ or \string\includegraphicobject}% + }% + \fi + \eappto\object@restorestandardfloats{\let\expandonce{\csname #1\endcsname}=\expandonce{\csname esf@original#1\endcsname}}% + }% + \fi +} + + +% ---------- default styles ---------- + +\NewObjectStyleGroup{all}{} + +\NewObjectStyle{table}{type=table} +\NewObjectStyle{figure}{type=figure} + + +% ========== include graphic object ========== + +\newif\ifgraphicobject@autocaption +\newif\ifgraphicobject@autolabel +\newif\ifgraphicobject@autocaption@strippath +\newif\ifgraphicobject@autolabel@strippath +\newif\ifgraphicobject@warnenv +\newif\ifgraphicobject@noenv + +\ifesf@loadgraphics + +\newcommand\object@graphic@env{figureobject} +\newcommand\object@graphic@path{/object} +\newcommand\object@graphic@options{} + +\newrobustcmd{\graphicobjectstyle}[1]{% + \IfObjectStyleNotGroup{#1}{% + \def\object@graphic@env{#1object}% + }{% + \PackageError{easyfloats}{Undefined object style: '#1'}{}% + }% +} + +% do not confuse this with \CheckObjectGraphicOption +% this corresponds to \CheckObjectOption +\newcommand{\CheckGraphicobjectOption}[2]{% #1: key, #2: value, #3: executed if valid + % if #3 is *not* executed an error message is printed + \let\CheckGraphicobjectOption@handleArg=\@gobble + \esf@ifpgfkeyexists{/graphicobject/#1}{% + \esf@ifpgfkeyrequiresvalue{/graphicobject/#1}{% + \ifx \pgfkeysnovalue #2\relax + \PackageError{easyfloats}{The key '#1' requires a value. I am going to ignore this key}{}% + \else + \let\CheckGraphicobjectOption@handleArg=\@firstofone + \fi + }{% + \let\CheckGraphicobjectOption@handleArg=\@firstofone + }% + }{\esf@ifkeyvalkeyexists{Gin}{#1}{% + \esf@ifkeyvalkeyrequiresvalue{Gin}{#1}{% + \ifx \pgfkeysnovalue #2\relax + \PackageError{easyfloats}{The key '#1' requires a value. I am going to ignore this key}{}% + \else + \let\CheckGraphicobjectOption@handleArg=\@firstofone + \fi + }{% + \let\CheckGraphicobjectOption@handleArg=\@firstofone + }% + }{% + \PackageError{easyfloats}{'#1' is not a valid graphic option key} + {If you intended to use a graphbox option please make sure that you loaded this package with the option 'graphbox'.}% + }}% + \CheckGraphicobjectOption@handleArg +} + +\newcommand{\AppendGraphicobjectOption}[2]{% #1: key, #2: value + \AppendToOptionsList{\object@graphic@options}{#1}{#2}% +} +\newcommand{\includegraphicobject@SetGraphicobjectOption}[2]{% #1: key, #2: value + \pgfkeysalso{#1={#2}}% +} + +% available options +\pgfqkeys{/graphicobject}{% + auto caption/.is if=graphicobject@autocaption, + auto caption=true, + % + auto label/.is if=graphicobject@autolabel, + auto label=true, + % + auto caption strip path/.is if=graphicobject@autocaption@strippath, + auto caption strip path=false, + % + auto label strip path/.is if=graphicobject@autolabel@strippath, + auto label strip path=false, + % + warn env/.is if=graphicobject@warnenv, + warn env=true, + % + no env/.is if=graphicobject@noenv, + no env=true, +} + +\newrobustcmd{\includegraphicobject}{% [#1: graphicstyle], [#2: options], #3: graphic filename without extension + \let\includegraphicobject@after=\@empty + \@ifnextchar [% + \includegraphicobject@firstarg + \includegraphicobject@parseoptions +} +\def\includegraphicobject@firstarg[#1]{% + \begingroup + \@ifnextchar [% + {% + \begingroup + \let\includegraphicobject@after=\endgroup + \graphicobjectstyle{#1}% + \includegraphicobject@parseoptions + }% + {% + \includegraphicobject@parseoptions[#1]% + }% +} + +\newcommand{\includegraphicobject@parseoptions}{% [#1: options], #2: graphic filename without extension + % expanding \object@graphic@env before is important for subcaptionbox + % otherwise I get the error \begin{subobject} ended by \end{subobject} + \@ifnextchar [ + {\expandafter\includegraphicobject@do\expandafter{\object@graphic@env}} + {\expandafter\includegraphicobject@do\expandafter{\object@graphic@env}[]}% +} +\def\includegraphicobject@do#1[#2]#3{% #1: environment name, #2: options, #3: graphic filename without extension + \global\object@isgraphictrue + \begin{#1}{% + /utils/exec=\def\object@graphic@options@tmp{}% + \let\AppendGraphicobjectOption\includegraphicobject@SetGraphicobjectOption, + .unknown/.code={% + \esf@ifkeyvalkeyexists{Gin}{\pgfkeyscurrentname}{% + \AppendToOptionsList{\object@graphic@options@tmp}{\pgfkeyscurrentname}{##1}% + }{% + \let\pgfkeys@searchalso@name=\pgfkeyscurrentname + \pgfkeysalso{% + /graphicobject/\pgfkeys@searchalso@name={##1}, + }% + }% + }, + .esf@also from=\object@graphic@options, + #2, + /utils/exec= + \ifgraphicobject@autocaption + \esf@ifpgfkeyhasvalue{\object@graphic@path/caption}{% + % do nothing + }{% + \def\graphicobject@caption{#3}% + \PatchUnderscore\graphicobject@caption + \ifgraphicobject@autocaption@strippath + \protected@edef\graphicobject@caption{\strippath\graphicobject@caption}% + \fi + \pgfkeyslet{\object@graphic@path/caption}{\graphicobject@caption}% + }% + \fi + \ifgraphicobject@autolabel + \esf@ifpgfkeyhasvalue{\object@graphic@path/label}{% + % do nothing + }{% + \def\graphicobject@label{#3}% + \ifgraphicobject@autolabel@strippath + \protected@edef\graphicobject@label{\strippath\graphicobject@label}% + \fi + \pgfkeyslet{\object@graphic@path/label}{\graphicobject@label}% + }% + \fi + \ifgraphicobject@warnenv + \pgfkeysalso{env/.get=\esf@tmp@env}% + \ifx \esf@tmp@env \@empty + \else + \ifdefstring{\object@graphic@env}{subobject} + {\edef\esf@tmp@name{\string\includegraphicsubobject}} + {\edef\esf@tmp@name{\string\includegraphicobject}}% + \ifgraphicobject@noenv + \PackageWarning{easyfloats}{I am ignoring 'env=\esf@tmp@env' in \esf@tmp@name}% + \else + \PackageWarning{easyfloats}{'env=\esf@tmp@env' in \esf@tmp@name. Is that intended?}% + \fi + \fi + \fi + \ifgraphicobject@noenv + \pgfkeysalso{env=}% + \fi + , + } + \expandafter\includegraphics\expandafter[\object@graphic@options@tmp]{#3}% + \end{#1}% + % if this is \@empty it should not interfere with \ignorespacesafterend (\ignorespaces) or \@endparenv (\@doendpe) + \includegraphicobject@after +} + +\newrobustcmd{\includegraphicsubobject}{% + \begingroup + \def\object@graphic@env{subobject}% + \def\object@graphic@path{/subobject}% + \def\includegraphicobject@after{\endgroup\ignorespaces}% + \includegraphicobject@parseoptions +} + + +\fi %\ifesf@loadgraphics + + +% ========== sub object ========== + +\newif\ifsubobject@warnnolabel +\newif\ifsubobject@warnnocaption + +% available options +\pgfqkeys{/subobject}{% + % A label for the left/right part of the content + label/.initial, + label/.value required, + % + % A caption displayed above or below the sub content + % (depending on the float style). + % There is *no* dot added automatically behind it. + caption/.initial, + caption/.value required, + % + % A caption used in the list of figures/tables/... + % for the left/right part of the content. + list caption/.initial, + list caption/.value required, + % + % An addition to the caption (at the object only, not in a list) + details/.initial=, + details/.value required, + % + details sep/.initial=.\space, + details sep/.value required, + % + % TeX code which is inserted before env + exec/.initial=, + exec/.value required, + exec +/.code=\esf@pgfkeysvalueappend{/subobject/exec}{#1}, + exec +/.value required, + exec+/.forward to=/subobject/exec +, + exec+/.value required, + % + % The width argument of \subcaptionbox or subfigure. + % For \subcaptionbox an empty value is allowed + % meaning that the argument is not passed so that + % \subcaptionbox takes the width of the content. + linewidth/.initial=.5\linewidth, + linewidth/.value required, + % + % Use the \subcaptionbox command. + % Aligns the captions. + % Does not allow verbatim content. + % Is *not* compatible with env=tabularx. + subcaptionbox/.code= + \let\subobject@begin\subobject@subcaptionbox + \let\subobject@end\endsubobject@subcaptionbox, + subcaptionbox/.value forbidden, + % Use the subfigure/subtable environment. + % Requires linewidth. + subpage/.code= + \let\subobject@begin\subobject@subpage + \let\subobject@end\endsubobject@subpage, + subpage/.value forbidden, + % + % ------- subcaptionbox options ------- + % Horizontal position of the content in the box. + % Allowed values: c, l, r, s, or any + % justification defined with \DeclareCaptionJustification + % (see the caption package documentation). + % An empty value means that this optional argument is + % *not* passed to the \subcaptionbox command. + % This option has no effect if linewidth is empty. + % I discourage using this option because it destroys + % the alignment of (sub)object and (sub)caption. + subcaptionbox inner pos/.initial=, + subcaptionbox inner pos/.value required, + % + % ------- subfigure/subtable options ------- + % The subfigure/subtable environments are minipages + % and take the same arguments. + % http://tug.org/texinfohtml/latex2e.html#minipage + % + % The vertical position of the minipage on the baseline. + % Allowed values: c, t, b, auto, . + % auto means t if the caption is displayed at the top + % or b if the caption is displayed at the bottom + % so that the captions are aligned if the minipages + % have the same height. + % is equivalent to c. + subpage outer pos/.initial=auto, + subpage outer pos/.value required, + % + % The height of the minipage. + % An empty value means that this optional argument is + % *not* passed to the subfigure/subtable environment. + subpage height/.initial=, + subpage height/.value required=, + % + % The vertical position of the content on the minipage. + % Allowed values: t, c, b, s, . + % means that this optional argument is + % *not* passed to the subfigure/subtable environment. + % This option has no effect if subpage height is . + subpage inner pos/.initial=, + subpage inner pos/.value required, + % + % TeX code which is inserted at the beginning of the subfigure/subtable environment + subpage align/.initial=\centering, + subpage align/.value required, + % + % ------- separator options ------- + % Insert a separator in front of each subobject + % except for the first subobject. + sep/.initial=, + sep/.value required, + % + % Place the subobjects side by side. + hor/.code= + \esf@pgfkeyscopyvalue{/subobject/sep}{/subobject/hor sep}% + \esf@pgfkeysvalueappend{/subobject/sep}{#1}, + hor/.default=, + % + % The separator to be used when the subobjects + % shall be placed side by side. + hor sep/.initial=, + hor sep/.value required, + hor sep+/.forward to=/subobject/hor sep +, + hor sep+/.value required, + hor sep +/.code=\esf@pgfkeysvalueappend{/subobject/hor sep}{#1}, + hor sep +/.value required, + % + % Place the subobjects below each other. + ver/.code= + \esf@pgfkeyscopyvalue{/subobject/sep}{/subobject/ver sep}% + \esf@pgfkeysvalueappend{/subobject/sep}{#1}, + ver/.default=, + % + % The separator to be used when the subobjects + % shall be placed below eachother. + ver sep/.initial=\par\bigskip, + ver sep/.value required, + ver sep+/.forward to=/subobject/ver sep +, + ver sep+/.value required, + ver sep +/.code=\esf@pgfkeysvalueappend{/subobject/ver sep}{#1}, + ver sep +/.value required, + % + % + % ------- warnings ------- + % + warn no caption/.is if=subobject@warnnocaption, + warn no caption=true, + % + warn no label/.is if=subobject@warnnolabel, + warn no label=false, + % + warn other env/.forward to=/object/warn other env, + %value is allowed but not necessary + % + % + % ------- debugging ------- + % + show env args/.forward to=/object/show env args, + % + % + % ------- inner environment ------- + % + % An additional inner environment to wrap the content in like tabular, tabularx, tikzpicture + env/.code=\IfEnvironmentExistsOrIsEmpty{#1}{% + \ifstrequal{#1}{longtable}{% + \PackageError{easyfloats}{You cannot use 'env=longtable' in a subobject} + {Either use 'env=tabular' instead or combine the subobjects into one longtable.}% + \pgfkeyssetvalue{/subobject/env}{tabular}% + }{% + \pgfkeyssetvalue{/subobject/env}{#1}% + }% + }{% + \PackageError{easyfloats}{Environment #1 which you passed to the key 'env' does not exist}{}% + }, + env/.value required, + env=, + % + % ------- unknown handler / env args ------- + % + % see /object + % + .unknown/.code={% + % Using \ObjectProcessKeyPattern instead of \ObjectProcessArgs + % means that keys like `graphic width` can be used in subobjects as well. + % For a directly used subobject this should not be allowed. + % But I am leaving it in for \includegraphicsubobject so that the same key + % which works in \objectset and \includegraphicobject also works there. + \ObjectProcessKeyPattern{\pgfkeyscurrentname}{#1}{% + \pgfkeysgetvalue{/subobject/.really unknown/.@cmd}{\esf@tmp@err}% + \esf@tmp@err#1\pgfeov + }% + }, + % Setting an unknown key handler shall not override env args but set an additional unknown handler. + .unknown/.code/.code={% + \pgfkeysdef{/subobject/.really unknown}{#1}% + }, + .really unknown/.code={% + \edef\do{\noexpand\pgfkeys{/errors/unknown key={\pgfkeyscurrentkey}{\unexpanded{#1}}}}% + \do + }, +}% + +\newenvironment{subobject}[1]{% #1: options + \if@inobject + \else + \PackageError{easyfloats}{subobject environment may not be used outside of an object}{Did you mean to use the object environment instead?}% + \fi + % + \subobject@hook + \ifobject@isgraphic + \object@graphic@hook + \global\object@isgraphicfalse + \fi + % + \let\label=\esf@original@label + \let\caption=\esf@original@caption + % + % ------- options ------- + % + \renewcommand\@object@envkey{/subobject/env}% + \pgfqkeys{/subobject}{#1}% + \ifsubobject@warnnocaption + \pgfkeys{/subobject/caption/.esf@recommended}% + \fi + \ifsubobject@warnnolabel + \pgfkeys{/subobject/label/.esf@recommended}% + \fi + % + \esf@ifpgfkeyhasvalue{/subobject/list caption}% + {\pgfkeys{/subobject/list caption/.get=\subobject@caption@short}}% + {\pgfkeys{/subobject/caption/.get=\subobject@caption@short}}% + \pgfkeysgetvalue{/subobject/linewidth}{\subobject@linewidth}% + % + \pgfkeysgetvalue{/subobject/details}{\subobject@details}% + \ifx \subobject@details \@empty + % do nothing + \else + \preto\subobject@details{\pgfkeysvalueof{/subobject/details sep}}% + \fi + % + \pgfkeysgetvalue{/subobject/env}{\esf@tmp@env}% + \ifx \esf@tmp@env \@empty + \def\subobject@innerenv@begin{\ignorespaces}% + \def\subobject@innerenv@end{\unskip}% + \else + \edef\subobject@innerenv@begin{\expandonce{\csname\esf@tmp@env\endcsname}}% + \edef\subobject@innerenv@end{\expandonce{\csname end\esf@tmp@env\endcsname}}% + \ObjectAppendEnvargs{\subobject@innerenv@begin}% + \ifobject@showenv + \show\subobject@innerenv@begin + \fi + \fi + % + % ------- execute ------- + % + \if@firstsubobject + \else + % No need to worry about \parskip. + % Inside of a floating environment it appears to be always zero. + \pgfkeysvalueof{/subobject/sep}% + \fi + \subobject@begin +}{% + \subobject@end + \global \@firstsubobjectfalse +} + +\NewEnviron{subobject@subcaptionbox}{% + \def\subobject@box{% + \subcaptionbox[% list caption + \subobject@caption@short + ]{% caption + \pgfkeysvalueof{/subobject/caption}% + \subobject@details + \esf@ifpgfkeyhasvalue{/subobject/label} + {\label{\pgfkeysvalueof{/subobject/label}}} + {}% + }% + }% + \ifdefvoid\subobject@linewidth{% + % do nothing + }{% + \appto\subobject@box{[\subobject@linewidth]}% + \pgfkeysgetvalue{/subobject/subcaptionbox inner pos}{\subobject@innerpos}% + \ifx \subobject@innerpos \@empty + % do nothing + \else + \eappto\subobject@box{[\subobject@innerpos]}% + \fi + }% + \subobject@box{% content + \begingroup + \renewcommand{\label}[1]{\PackageError{easyfloats}{\string\label\space is not allowed in subobject. Please use the 'label' option instead}{}}% + \renewcommand{\caption}[2][]{\PackageError{easyfloats}{\string\caption\space is not allowed in subobject. Please use the 'caption' option instead}{}}% + \pgfkeysvalueof{/subobject/exec}% + \subobject@innerenv@begin + \BODY + \subobject@innerenv@end + \endgroup + }% +} + +\newenvironment{subobject@subpage}{% + \ifx \subobject@linewidth \@empty + \PackageError{easyfloats}{'linewidth' may not be empty when using the 'subpage' backend}{}% + \fi + \edef\subobject@subpage@envname{sub\pgfkeysvalueof{/object/type}}% + \def\subobject@subpage@begin{\csname\subobject@subpage@envname\endcsname}% + \def\subobject@subpage@end{\csname end\subobject@subpage@envname\endcsname}% + % + \pgfkeysgetvalue{/subobject/subpage outer pos}{\subobject@outerpos}% + \ifx \subobject@outerpos \@empty + \appto\subobject@subpage@begin{[c]}% + \else \ifdefstring \subobject@outerpos {auto}{% + \caption@iftop + {\eappto\subobject@subpage@begin{[t]}}% + {\eappto\subobject@subpage@begin{[b]}}% + }{\ifdefstring \subobject@outerpos {Auto}{% + \caption@iftop + {\eappto\subobject@subpage@begin{[T]}}% + {\eappto\subobject@subpage@begin{[B]}}% + }{% + \eappto\subobject@subpage@begin{[\subobject@outerpos]}% + }}\fi + \pgfkeysgetvalue{/subobject/subpage height}{\subobject@height}% + \ifx \subobject@height \@empty + \else + \appto\subobject@subpage@begin{[\subobject@height]}% + \pgfkeysgetvalue{/subobject/subpage inner pos}{\subobject@innerpos}% + \ifx \subobject@innerpos \@empty + \else + \eappto\subobject@subpage@begin{[\subobject@innerpos]}% + \fi + \fi + % + \subobject@subpage@begin{\subobject@linewidth}% + \pgfkeysvalueof{/subobject/subpage align}% + % \caption@iftop is defined by caption package + \caption@iftop{\subobject@subpage@captionAndLabel}{}% + \begingroup + \renewcommand{\label}[1]{\PackageError{easyfloats}{\string\label\space is not allowed in subobject. Please use the 'label' option instead}{}}% + \renewcommand{\caption}[2][]{\PackageError{easyfloats}{\string\caption\space is not allowed in subobject. Please use the 'caption' option instead}{}}% + \pgfkeysvalueof{/subobject/exec}% + \subobject@innerenv@begin +}{% + \subobject@innerenv@end + \endgroup + \caption@iftop{}{\subobject@subpage@captionAndLabel}% + \subobject@subpage@end + \ignorespacesafterend +} +\newcommand{\subobject@subpage@captionAndLabel}{% + % ------- caption ------- + % position of caption (above/below) is handled by float package (see float style) + \esf@ifpgfkeyhasvalue{/subobject/caption}{% + \caption[\subobject@caption@short]{\pgfkeysvalueof{/subobject/caption}\subobject@details}% + }{% + % Generate an anchor for a \label. + \phantomcaption + }% + % ------- label ------- + \esf@ifpgfkeyhasvalue{/subobject/label}% + {\label{\pgfkeysvalueof{/subobject/label}}}% + {}% +} + +\pgfqkeys{/subobject}{subpage} diff --git a/Master/texmf-dist/source/latex/easyfloats/easyfloats.ins b/Master/texmf-dist/source/latex/easyfloats/easyfloats.ins new file mode 100644 index 00000000000..c3f1020483b --- /dev/null +++ b/Master/texmf-dist/source/latex/easyfloats/easyfloats.ins @@ -0,0 +1,82 @@ +% !TeX program = tex + +%% easyfloats.ins +%% Copyright 2020 E. Zöllner +% +% This work may be distributed and/or modified under the +% conditions of the LaTeX Project Public License, either version 1.3 +% of this license or (at your option) any later version. +% The latest version of this license is in +% http://www.latex-project.org/lppl.txt +% and version 1.3 or later is part of all distributions of LaTeX +% version 2005/12/01 or later. +% +% This work has the LPPL maintenance status `maintained'. +% +% The Current Maintainer of this work is E. Zöllner. +% +% This work consists of the files listed in easyfloats-file-list.txt. +% The official git repository is https://gitlab.com/erzo/latex-easyfloats + + +% Make easyfloats.dtx faster by stripping comments and indentation +% and write the result to easyfloats.sty. + +\input docstrip.tex + +\preamble + +Copyright 2020 E. Z\string\"ollner + +This work may be distributed and/or modified under the +conditions of the LaTeX Project Public License, either version 1.3 +of this license or (at your option) any later version. +The latest version of this license is in + http://www.latex-project.org/lppl.txt +and version 1.3 or later is part of all distributions of LaTeX +version 2005/12/01 or later. +Additionally to the rights granted by the LaTeX Project Public License +you have permission to freely distribute unmodified copies +of the files \jobname.sty and doc/easyfloats.pdf without other files of this work. +The other files of this work can be found at: +https://gitlab.com/erzo/latex-easyfloats + +This work has the LPPL maintenance status `maintained'. + +The Current Maintainer of this work is E. Z\string\"ollner. + +This work consists of the files listed in easyfloats-file-list.txt. +\endpreamble + +\askforoverwritefalse +\generate{ + \file{\jobname.sty}{\from{\jobname.dtx}{package}} +} + +\def\lnout{} +\count0=0 +\def\append#1{\advance\count0 by 1 \expandafter\def\expandafter\lnout\expandafter{\lnout#1}} +\def\appendmany#1{\ifx\relax#1\else\append{#1}\expandafter\appendmany\fi} +\obeyspaces +\appendmany \relax +\expandafter\appendmany\jobname.sty\relax +\loop\append{ }\ifnum\count0<48\repeat +\Msg{****************************************************} +\Msg{* *} +\Msg{* To finish the installation you have to move the *} +\Msg{* following file into a directory searched by TeX: *} +\Msg{* *} +\Msg{* \lnout *} +\Msg{* *} +\Msg{* To produce the documentation run: *} +\Msg{* $ cd doc *} +\Msg{* $ pdflatex easyfloats.tex *} +\Msg{* $ biber easyfloats *} +\Msg{* $ pdflatex easyfloats.tex *} +\Msg{* $ pdflatex easyfloats.tex *} +\Msg{* *} +\Msg{* Happy TeXing! *} +\Msg{* *} +\Msg{****************************************************} + +\endbatchfile -- cgit v1.2.3