为基于 minipage/tabular/etc 的新环境推出我自己的脚注命令

为基于 minipage/tabular/etc 的新环境推出我自己的脚注命令

我以为我已经解决了表格中的脚注问题,\makesavenoteenv但是它与 Minted 包交互很差所以我想,既然我的问题实际上是“让脚注在我的盒子环境中工作”,也许我可以创建一个新的脚注命令来排队脚注,可以在环境结束时将其添加到页面中。

\documentclass{article}

% let ASIDE_FOOTNOTES be an empty list

\newcommand\asidefootnote[1]%
{%
    \footnotemark{}%
    % add #1 to ASIDE_FOOTNOTES list
}

\newcommand\emitasidefootnotes%
{
    % where SIZE is the length of the ASIDE_FOOTNOTES list
    % \addtocounter{footnote}{-SIZE}

    % for each NOTE in ASIDE_FOOTNOTES
    % \footnotetext{NOTE}

    % let ASIDE_FOOTNOTES be an empty list
}

\newenvironment{aside}[1]
{
    \begin{minipage}{0.5\textwidth}
    ASIDE (#1) \par
}
{
    \end{minipage}
    \emitasidefootnotes
}

\begin{document}

Foo\footnote{foonote}

\begin{aside}{advanced}
    aaa\asidefootnote{foo aaa} bbb\asidefootnote{foo bbb}
\end{aside}

Bar\footnote{barnote}

\begin{aside}{advanced}
    xxx\asidefootnote{foo xxx} zzz\asidefootnote{foo zzz}
\end{aside}

Baz\footnote{baznote}

\end{document}

基本上,我需要将上述注释转化为实际的代码。

  1. 的参数\asidefootnote可以是任意的。
  2. 它不能干扰其他正常的脚注。在上面的例子中,脚注 1 到 7 应该按照自然顺序一起出现在页面底部。
  3. 没有需要递归工作(一个aside环境永远不会aside直接或间接包含另一个环境,也不会包含使用此技巧的任何其他环境)。

我该如何实现这一点?(换句话说,如何将 tex 块添加到列表中,将该列表的大小传递给\addtocounter,遍历该列表,并清空该列表?)

答案1

这可以完成工作,但有点儿不妥。如果有人发布更好的纯 tex 解决方案(但这应被视为参考实现),我将暂缓接受自己的答案。

我将\asidefootnote其脚注文本写入一个文件,然后\emitasidefootnotes调用一个 Perl 脚本读取该文件并生成具有正确编号的脚注。

\documentclass{article}
\usepackage{mdframed}
\usepackage{xcolor}

% Taken from https://gist.github.com/w495/7328b76e76aee49657e0bd7a3b46c870
% This runs a bash command and prits the first line of its output into the
% document
\makeatletter
    \newcommand{\bashline@file@name}[1]{%
        /tmp/${USER}-${HOSTNAME}-\jobname-#1.tex%
    }
    \newread\bashline@file
    \newcommand{\bashline@command@one}[2][tmp]{%
        \immediate\write18{#2 > \bashline@file@name{#1}}
        \openin\bashline@file=\bashline@file@name{#1}
        % The group localizes the change to \endlinechar
        \bgroup
            \endlinechar=-1
            \read\bashline@file to \localline
            % Since everything in the group is local, 
            % we have to explicitly make the assignment global
            \global\let\bashline@result\localline
        \egroup
        \closein\bashline@file
        % Clean up after ourselves
        \immediate\write18{rm \bashline@file@name{#1}}
        \bashline@result
    }
    \newcommand{\bashline@command@many}[2][tmp]{%
        \immediate\write18{#2 > \bashline@file@name{#1}}
        \openin\bashline@file=\bashline@file@name{#1}
        % The group localizes the change to \endlinechar
        \newcount\linecnt
        \bgroup
            \endlinechar=-1
            \loop\unless\ifeof\bashline@file 
                \read\bashline@file to \localline%
                \localline
                \newline
            \repeat
        \egroup
        \closein\bashline@file
        % Clean up after ourselves
        \immediate\write18{rm \bashline@file@name{#1}}
    }
    \newcommand{\bashline}[2][tmp]{%
        \bashline@command@one[#1]{#2}%
    }
    \newcommand{\bashlines}[2][tmp]{%
        \bashline@command@many[#1]{#2}%
    }
\makeatother

% The \asidefootnote and \emitasidefootnotes commands
\def\asideinpfilename{aside.inp}
\def\asidetexfilename{aside.out}

\newwrite\asidefile
\immediate\openout\asidefile=\asideinpfilename
%\immediate\write\asidefile{ASIDES-START-HERE}

\newcommand{\asidefootnote}[1]%
{%
    \footnotemark{}%
    \immediate\write\asidefile{\unexpanded{#1}}%
}

\newcommand{\emitasidefootnotes}%
{%
    \immediate\closeout\asidefile%
    \bashline{perl bin/emit-aside-foonotes.pl '\asideinpfilename' '\asidetexfilename'}%
    \input{\asidetexfilename}%
    \immediate\openout\asidefile=\asideinpfilename%
}

\newenvironment{aside}[1]
{
    \mdfsetup{%
       middlelinecolor=red,
       middlelinewidth=2pt,
       backgroundcolor=red!5}
    \begin{mdframed}
    ASIDE (#1) \par
}
{
    \end{mdframed}
    \emitasidefootnotes
}

\begin{document}

Foo\footnote{foonote}

\begin{aside}{intermediate}
    aaa\asidefootnote{foo

    \begin{tabular}{|l|l|}
            \hline
            a & b \\ \hline
            c & d \\ \hline
    \end{tabular}}
    bbb\asidefootnote{foo bbb}
\end{aside}

Bar\footnote{barnote}

\begin{aside}{advanced}
    xxx\asidefootnote{foo xxx} zzz\asidefootnote{foo zzz}
\end{aside}

Baz\footnote{baznote}

\end{document}

Perl 脚本bin/emit-aside-footnotes.pl如下所示:

#!/usr/bin/perl
use strict;

die "Needs arguments: infile outfile" if (2 != @ARGV);

my $in_name  = $ARGV[0];
my $out_name = $ARGV[1];

open (my $in,  "<", $in_name)  or die $!;
open (my $out, ">", $out_name) or die $!;

my @lines = <$in>;

my $n = @lines;

exit if (0 == $n);

print $out "\\addtocounter{footnote}{-$n}";

chomp and print $out "\\stepcounter{footnote}\\footnotetext{$_}"
foreach (@lines);

结果:

在此处输入图片描述

请注意,会\immediate\write\asidefile{\unexpanded{#1}}自动写入单身的即使文件#1包含多行 tex,它也使多行脚注 2 成为可能。

相关内容