複数段組の現在の列を検出する

複数段組の現在の列を検出する

私は 2 列のマルチコル環境で作業しており、wrapfig を使用してプル クォートを作成しようとしています。問題は、これらのプル クォートをマージン内に配置したいことです。つまり、左列の場合は左マージン、右列の場合は右マージンに配置したいのです。

現在の列番号を検出して、wrapfig に「列番号 = 1 の場合は図を左に掛け、列番号 = 2 の場合は右に掛ける」と指示する方法はありますか? このようなテキストがたくさんあるので、これをすべて手動で設定するのはかなり面倒です。

これを使ってみましたプルクォートパッケージしかし、これまでのところ、マイクロタイプ エラーが多数発生しています (XeLaTeX を使用しています)。

編集: ある種の MWE は次のようになります。明らかに\imaginarycolumnnumberidentifierこれが私が求めているものです。明らかにこれは「動作する」例ではありませんし、実際に etoolbox を使用したことがないので、このコードには他の問題があるかもしれませんが、考え方は理解できると思います。

\documentclass{article}
\usepackage{multicol}
\usepackage{wrapfig}
\usepackage{lipsum}
\usepackage{etoolbox}

\newenvironment{pquote}{%
  \begin{wrapfigure}[3]{%
      \ifnumequal{1}{\imaginarycolumnnumberidentifier}{l}{r}%
    }[0.2\columnwith]{0.4\columnwidth}
  }{%
  \end{wrapfigure}}

\begin{document}

\begin{multicols}{2}
\lipsum[1]
\begin{pquote}
  Lorem ipsum!
\end{pquote}
\lipsum[2]
\begin{pquote}
  dolor sit amet!
\end{pquote}
\lipsum[3]
\end{multicols}

\end{document}

画像を投稿するには評判が足りないので、出力結果は想像するしかありません。信じてください、最初の pquote は左側にあり、2 番目の pquote は右側にあります。私の心の中では。

画像

答え1

twocolumnパッケージ経由ではなくレイアウトにこれを実装する方法を説明しますmulticol。これにより、コーディングの問題の一部が修正されます。

サンプル出力

\documentclass[twocolumn]{article}

\usepackage{wrapfig}
\usepackage{lipsum}

\makeatletter
\newenvironment{pquote}[1][\relax]{%
  \ifx#1\relax\def\@mypl{\if@firstcolumn l\else r\fi}%
  \else\def\@mypl{#1}\fi%
  \wrapfigure[3]{\@mypl}[0.2\columnwidth]{0.4\columnwidth}%
  \large\bfseries}{\par\endwrapfigure}
\makeatother

\begin{document}

\lipsum[1]
\begin{pquote}
  Lorem ipsum!
\end{pquote}
\lipsum[2-4]
\begin{pquote}
  Dolor sit amet!
\end{pquote}
\lipsum[5-8]
\begin{pquote}[r]
   Mauris ut est.
\end{pquote}
\lipsum[9]

\end{document}

残念ながら、のpquoteバリエーションを設定する一般的な方法は機能しません。これは、固定位置の簡単なテスト ドキュメントを作成するとわかります。これは、引数の処理方法に関係しています。代わりに、適切な引数とともに を使用し、 とバランスをとってください。さらに、位置指定引数は、許可された文字列の 1 つに直接展開する必要があるため、これは中間マクロを介して行う必要があります。wrapfigure\begin{wrapfigure}\wrapfigure\endwrapfigure

これで、配置を決定するために使用できるtwocolumnテストができました。残念ながら、これは 100% 確実ではないため、上記の定義では、配置を強制できるオプションの引数を提供しています。\if@firstcolumn

ではmulticols状況がかなり複雑で、これを行うための簡単にアクセスできる変数は見当たりません。基本的に、 は のmulticol資料を 1 つの長いボックスにタイプセットし、各列の上から正しい量だけ分割します。列番号をカウントする内部変数がいくつかありますが、簡単にアクセスすることはできません。さらに、 はmulticol列のバランスを調整し、 の指定されたタイプセットされた資料を同じ高さのいくつかのボックスに分割しようとしますが、その過程でタイプセットが変更される場合は、さらに複雑になります。このことの 1 つの兆候は、\marginparでは が許可されないことですmulticols(パッケージのドキュメントを参照)。一方、twocolumnmargin では pars は (かなり) 適切に機能し、必要に応じて左右を切り替えます。

追加コメントへの返信:

を使用しmulticols、配置を指定する準備ができている場合は、コーディングはより簡単になりますが、それでも以下を避ける必要があります\begin{wrapfigure}

複数段出力のサンプル

\documentclass{article}

\usepackage{multicol,ragged2e}
\usepackage{wrapfig}
\usepackage{lipsum}

\makeatletter
\newenvironment{pquote}[2]{%
  \wrapfigure[#1]{#2}[0.2\columnwidth]{0.4\columnwidth}%
  \large\bfseries\Centering}{\par\endwrapfigure}
\makeatother

\begin{document}

\begin{multicols}{2}
  \lipsum[1]
  \begin{pquote}{4}{l}
    Lorem ipsum!
  \end{pquote}
  \lipsum[2-4]
  \begin{pquote}{6}{r}
    Dolor sit amet!
  \end{pquote}
  \lipsum[5-8]
  \begin{pquote}{5}{r}
    Mauris ut est.
  \end{pquote}
  \lipsum[9]
\end{multicols}
\end{document}

答え2

Andrew が回答で述べたように、複数段組の解決法は、タイプ設定中に「現在の」列がまったくわからないため、かなり複雑です。そのため、(ファイルを使用して.aux) 複数回タイプ設定を実行する、かなり複雑なアプローチが必要です。

以下は、列タイプに応じて条件付きコードを実行するためのソリューションの最初のドラフトです\docolaction{left}{middle}{right}。列タイプがまだ不明な場合は、最初の列が(デフォルトとして)想定されます。

\begin{filecontents}{mccolaction.sty}
%
%    \begin{macrocode}
\ProvidesPackage{mccolaction}
          [2013/05/05 v0.9b  column actions for multicolumn formatting (FMi)]
%    \end{macrocode}
%
%    \begin{macrocode}
\RequirePackage{etoolbox}
\RequirePackage{multicol}[2011/12/20]
%    \end{macrocode}
%    
%   Determining the current column in multicols is difficult because
%   (in contrast to the twocolumn mode of standard LaTeX) the
%   multicols columns are determined very late in the game and due to
%   the balancing routine it is not known where a piece of text is
%   going to end up at the time the text is typeset. Only afterwards,
%   when everything has be typeset into a single long galley, that
%   galley is split into individual columns (at the very end in a
%   possibly huge set of trials to balance the column material.
%
%   Therefore the approach taken here is to write out a single line
%   into the .aux file whenever a column is finally typeset:
%\begin{verbatim}
% \mc@col@status{<number>}
%\end{verbatim}
%   The number in the argument denotes the different kind of column: 1
%   for left column 2 for any middle column and 3 for the final column.
%
%   We only set this up for the LR typesetting case here, something
%   similar could be done for the RL version:
%    \begin{macrocode}
\patchcmd{\LR@column@boxes}{\box\count@}
         {\protected@write\@auxout{}{\string\mc@col@status
              {\ifmc@firstcol 1\else 2\fi}}%
          \mc@firstcolfalse
          \box\count@}
         {\typeout{juhu!}}{\typeout{oje!}}%

\patchcmd{\LR@column@boxes}{\box\mult@rightbox}
         {\protected@write\@auxout{}{\string\mc@col@status{3}}%
          \box\mult@rightbox}%
         {\typeout{juhu!}}{\typeout{oje!}}%

\newif\ifmc@firstcol
\mc@firstcoltrue
%    \end{macrocode}
%
%   Need to reinitiate \verb=\mc@align@columns= as this was let to
%   the old definition of \verb=\LR@column@boxes=.
%
%    \begin{macrocode}
\LRmulticolcolumns

%   Whenever we want to do something that depends on the current
%   column we execute \verb=\docolaction=. This command takes one
%   optional and three mandatory arguments. The mandatory ones denote
%   what to do if this is a ``left'', ``middle'', or ``right'' column
%   and the optional one is simply there to say what to do if we don't
%   know (default is to use the ``left'' column action in that case).
%
%   We use one counter \verb=\mc@col@check@num= to generate us unique
%   label names. Each time we execute \verb=\docolaction= we increment
%   this counter to get a new name.
%    \begin{macrocode}
\newcount\mc@col@check@num
%    \end{macrocode}

%   The generated ``labels'' are named
%   \verb=\mc@col-\the\mc@col@check@num= and they hold as values the
%   numbers 1, 2, or 3 denoting the current column type.

%    \begin{macrocode}
\newcommand\docolaction[4][1]{%
 \global\advance\mc@col@check@num\@ne
 \edef\mc@col@type{\expandafter\ifx
               \csname mc@col-\the\mc@col@check@num\endcsname\relax
                  0\else
                  \csname mc@col-\the\mc@col@check@num\endcsname
               \fi}%
%    \end{macrocode}
%    We prefix with 0 so that an unknown label (that returns
%   \verb=\relax=) will result in case 0
%    \begin{macrocode}
 \ifcase \mc@col@type\relax
%    \end{macrocode}
%    If column is unknown we use the default action or the action
%   denoted by the optional argument (so that arg can take the value
%   1, 2, 3)
%    \begin{macrocode}
     \ifcase #1\or #2\or#3\or#4\fi   % 0 not known use first col as default
  \or
%    \end{macrocode}
%    Otherwise we know (or think we know) that this is a first, middle,
%   or last column:
%    \begin{macrocode}
     #2%  % 1 First col
  \or
     #3%  % 2 any middle col
  \or  
     #4%  % 3 last col
  \else
    \ERROR
  \fi
%    \end{macrocode}
%    But how does the column number get associated with our label? We
%   do do this by writing another line into the aux file at this point:
%    \begin{macrocode}
  \edef\next{\write\@auxout
     {\string\mc@set@col@status{mc@col-\the\mc@col@check@num}%
                               {\mc@col@type}}}%
  \next
}
%    \end{macrocode}
%
%   Because of extra data writing to the aux file the aux file will
%   now contain something like the following after the document is
%   processed the first time:
%\begin{verbatim}
%\relax 
%\mc@col@status{1}
%\mc@set@col@status{lcol-1}{0}
%\mc@col@status{2}
%\mc@set@col@status{lcol-2}{0}
%\mc@col@status{3}
%\mc@set@col@status{lcol-3}{0}
%\mc@col@status{1}
%\mc@col@status{2}
%\mc@col@status{3}
%\mc@set@col@status{lcol-4}{0}
%\end{verbatim}
%   The \verb=\mc@col@status= line denotes the column type and has been
%   writting out just before corresponding the column box was placed
%   onto the page.
%   The\verb=\mc@set@col@status= lines have been written out as part
%   of shipping the column boxes out, e.g.,
%   \verb=\mc@set@col@status{lcol-1}{0}= was therefore somewhere within
%   the first column as it appears between \verb=\mc@col@status{1}=
%   and  \verb=\mc@col@status{2}=
%   The second argument in that line is the value used in the previous
%   run (or zero if there was no previous run. We can use this to
%   determine if a rerun is necessary.
%
%   Thus with this knowledge we can set things up to get the labels
%   working.
%
%   When the aux file is read in \verb=\mc@col@status= is used to set
%   \verb=\mc@curr@col@status=:
%
%    \begin{macrocode}
\def\mc@col@status#1{\gdef\mc@curr@col@status{#1}}
%    \end{macrocode}

%   And when \verb=\mc@set@col@status= is executed we can simply set
%   up the label by associating it with the \verb=\mc@curr@col@status=
%   and ignore the second argument:
%    \begin{macrocode}
\def\mc@set@col@status#1#2{%
   \global\expandafter\let\csname #1\endcsname\mc@curr@col@status}
%    \end{macrocode}
%
%   The above definition is being used when the \texttt{.aux} file is
%   read in at the beginning. At the end we need a different
%   definition to test if another typesetting run is needed. There we
%   compare the value used in the current run (stored in the second
%   argument) with the value used on the next run. If those two values
%   differ we set \verb=@tempswa= to false which will trigger the
%   ``Label(s) may have changed'' warning.
%    \begin{macrocode}
\AtEndDocument{\def\mc@set@col@status#1#2{%
     \ifnum #2=\mc@curr@col@status\else
       \@tempswatrue
     \fi}%
}
%    \end{macrocode}
\end{filecontents}

\documentclass{article}

\usepackage{mccolaction}

\usepackage{wrapfig}
\usepackage{lipsum}

% An application of \docolaction. We put the whole wrapfigure into the
% args so that the  internal label used is placed after wrapfigure.

\newcommand\pquote[2]{%
  \docolaction
     {\begin{wrapfigure}[#1]{l}[0.2\columnwidth]{0.4\columnwidth}%
        \raggedright\large\bfseries #2\end{wrapfigure}}%
     {\begin{wrapfigure}[#1]{l}[0pt]{0.4\columnwidth}%
        \raggedright\large\bfseries #2\end{wrapfigure}}%
     {\begin{wrapfigure}[#1]{r}[0.2\columnwidth]{0.4\columnwidth}%
        \raggedright\large\bfseries #2\end{wrapfigure}}%
  \ignorespaces
}


\setlength\columnseprule{.7pt}
\setlength\emergencystretch{2em}

\begin{document}

\begin{multicols}{3}
  \lipsum[1]
  \pquote{4}{Lorem ipsum!}
  \lipsum[2]
  \pquote{5}{Dolor sit amet!}
  \lipsum[4-5]
  \pquote{4}{Mauris ut est.}
  \lipsum[6-7]
  Only a few words left \ldots
  Here the pquote comes in the middle of the paragraph for a change
  \pquote{6}{Final test related to the edge}
  as we can see. Only a few words left so this drops off the column \ldots
\end{multicols}

\end{document}

このファイルを実行すると、

ここに画像の説明を入力してください

\pquote2 ページ目を見ると、すべてが完璧ではないことがわかりますが、これは、意図的に最後に近づけて配置したためです。

ここに画像の説明を入力してください

ファイルを 4 列を使用するように変更すると、列をまたいで 1 つの wrapfigure が切り取られることになります。これは明らかに、2 つのパッケージが十分に連携してこれを自動的に解決できないことが原因です。

ここに画像の説明を入力してください

要約すると、十分に機能していると言えます。同様のものと組み合わせると、wrapfigure場所によっては助けが必要になりますが、後で列を分割するマルチコルについては何もわからないため、これは予想されることですwrapfigure

アップデート

コードを少し改良したので、列タイプの変更も追跡できるようになりました。その結果、LaTeX をもう一度実行する必要があることが検出された場合は、「ラベルが変更された可能性があります。相互参照を正しくするために再実行してください。」というよく知られた警告が生成されます。

したがって、次のような出力は、ユーザーがその警告を無視した場合にのみ発生するはずです。

ここに画像の説明を入力してください

アップデート II

上記のバージョンは、mccolaction現時点でCTANに存在しないSVNバージョンに対して書かれたものです。複数段組の最初の列内のみで段区切りの両方のバージョンで動作する更新されたパッケージを提供しましたmulticol

アップデート III

上記の機能は、現在、multicol バージョン 1.8 以降で使用できます。この機能は自動的に有効にはなりません (コストがかかるため)。オプションを使用してリクエストする必要がありますcolaction。その後、\docolactionドキュメントで使用できるようになります。

関連情報