發送(並堆疊) \marginpar 到頁面頂部或底部

發送(並堆疊) \marginpar 到頁面頂部或底部
  • 我正在尋找類似的定義\topmarginpar{<text>},它本質上會創建一個\marginpar{<text>}並將其頂部與當前頁面的頂部對齊。

  • 我還希望多次\topmarginpar調用來堆疊這些\marginpar物件(而不是讓它們重疊)。

  • 最後我想創建一個類似的\bottommargin命令。

是否有一些現有的包提供此功能,或者我自己在這裡(我很流利的 LaTeX 但在原始 TeX 方面毫無價值)?

感謝您的任何建議...

答案1

此解決方案處理非同步輸出例程:

  • 頁面由絕對頁碼標識,並且在使用標籤的第二次 LaTeX 運行中可以獲得正確的頁碼。

  • 每頁都有兩個收集箱,用於收集頂部和底部的邊注。在發貨時,絕對頁碼是已知的,並且該頁的收集器框被輸出在該頁的“marginpar”區域中。

  • 框暫存器是動態分配的,並在池中進行管理。頁面輸出後,其收集器盒暫存器被釋放並放回池中。

  • \topskip\maxdepth因“marginpar”區域而受到尊重。

  • 頁面上過多的邊注會被報告為過滿\vbox警告。

  • 不支援LaTeX \marginpar,不同類型的邊注不互相認識,並且會很高興地互相套印。

範例文件:

\documentclass{article}

\usepackage{atbegshi}
\usepackage{zref-abspage}
\usepackage{picture}

\makeatletter
\providecommand*{\c@zabspage}{\c@abspage}

% * User macros for configuring
%
% \tbmparItemSep is inserted between marginal notes
% \tbmparMiddleSep is inserted between top and bottom marginal notes.

\newcommand*{\tbmparItemSep}{%
  \vspace{1ex minus .5ex}%
  \hrule
  \vspace{1ex minus .5ex}%
}
\newcommand*{\tbmparMiddleSep}{%
  \vspace*{0pt plus 1fil}%
}

% * Debug messages
%
\newcommand*{\tbmparDebug}[1]{%
  \typeout{[tbmpar] #1}%
}

% * Label management to remember absolute page number
%
% \tbmpar@PageByLabel stores and loads absolute page number from
% label and defines \tbmpar@page with absolute page number or
% zero if the label is not yet available.

\newcount\c@tbmpar@item
\c@tbmpar@item\z@

\newcommand*{\tbmpar@PageByLabel}{%
  \global\advance\c@tbmpar@item\@ne
  \zref@labelbyprops{tbmpar\the\c@tbmpar@item}{abspage}%
  \edef\tbmpar@page{%
    \zref@extractdefault{tbmpar\the\c@tbmpar@item}{abspage}{0}%
  }%
  \zref@refused{tbmpar\the\c@tbmpar@item}%
  \tbmparDebug{Item \the\c@tbmpar@item\space on page \tbmpar@page}%
}

% * Box register management

\newcount\c@tbmpar@box
\c@tbmpar@box\z@

\let\tbmpar@boxfreelist\@empty

% Get a new free box register either from the free list or,
% if the free list is empty, allocate a new box register.
\newcommand*{\tbmpar@NextBox}[1]{%
  \@next#1\tbmpar@boxfreelist{%  
    \tbmparDebug{Reused box: #1}%
  }{%
    \global\advance\c@tbmpar@box\@ne
    \expandafter\newbox\csname tbmpar@box\the\c@tbmpar@box\endcsname
    \edef#1{\csname tbmpar@box\the\c@tbmpar@box\endcsname}%
    \tbmparDebug{New box: #1}%
  }%
}
% Put free box in free list.
\newcommand*{\tbmpar@FreeBox}[1]{%
  \begingroup
    \let\@elt\relax
    \xdef\tbmpar@boxfreelist{%
      \tbmpar@boxfreelist
      \@elt#1%
    }%
    \tbmparDebug{Free box: #1}%
  \endgroup
}

\newsavebox{\tbmpar@box}

% Each marginpar is put in a box that is initialized as
% parbox/minipage.
\newcommand*{\tbmparBoxSetup}{}
\newcommand{\tbmpar@VBox}[1]{% 
  \vbox{%
    \color@begingroup
    \hsize\marginparwidth
    \edef\tbmpar@restore@ifminipage{%
      \if@minipage
        \noexpand\@minipagetrue
      \else
        \noexpand\@minipagefalse
      \fi
    }%   
    \@parboxrestore
    \@marginparreset
    \tbmparBoxSetup 
    #1%
    \tbmpar@restore@ifminipage
    \color@endgroup
  }%
}   

% Macro \tbmpar@marginpar looks for the page, where the margin note
% belongs to, stores the note in a box and appends the box to the  
% note collector register of the page.
% Each page is assigned a box collector registers that collect
% the top notes and a register that collect the bottom notes. 
% The name of the box register is \tbmpar@<top|bot>box<page>. 
\newcommand{\tbmpar@marginpar}[4]{%
  \ifhmode
    \@bsphack
  \fi
  \tbmpar@PageByLabel
  \ifnum\tbmpar@page>\z@
    \setbox\tbmpar@box\tbmpar@VBox{#4}%
    \@ifundefined{tbmpar@#1box\tbmpar@page}{%
      \tbmpar@NextBox\tbmpar@currbox
      \global\expandafter\let
          \csname tbmpar@#1box\tbmpar@page\endcsname
          \tbmpar@currbox
      \global\setbox\tbmpar@currbox=\vbox{%
        \unvbox\tbmpar@box
      }%
    }{% 
      \tbmparDebug{Use box: \tbmpar@currbox}%
      \expandafter\let\expandafter\tbmpar@currbox
          \csname tbmpar@#1box\tbmpar@page\endcsname
      \global\setbox\tbmpar@currbox\tbmpar@VBox{%   
        \unvbox#2%
        \par
        \begingroup
          \tbmparItemSep
        \endgroup
        \unvbox#3%
      }%
    }%  
  \fi   
  \ifhmode
    \@esphack
  \fi
}
\newcommand*{\topmarginpar}{%
  \tbmpar@marginpar{top}\tbmpar@currbox\tbmpar@box
}
\newcommand*{\botmarginpar}{%
  \tbmpar@marginpar{bot}\tbmpar@box\tbmpar@currbox
}

% At shipout time we look for the box collector registers of this
% page and set these boxes in the marginpar box with respecting  
% \topskip and \maxdepth.
\AtBeginShipout{%
  \AtBeginShipoutUpperLeft{%
    \put(%
      \dimexpr 1in+\oddsidemargin+\textwidth+\marginparsep\relax,%
      -\dimexpr 1in+\topmargin+\headheight+\headsep+\textheight\relax
    ){%
      \begingroup
        \global\let\tbmpar@inuse=N%
        \setbox\tbmpar@box=\tbmpar@VBox{%
          \penalty-\@M
          \edef\tbmpar@tmp{tbmpar@topbox\the\value{zabspage}}%
          \@ifundefined{\tbmpar@tmp}{%
          }{%
            \expandafter\let\expandafter\tbmpar@currbox
                \csname\tbmpar@tmp\endcsname
            \unvbox\tbmpar@currbox
            \tbmpar@FreeBox\tbmpar@currbox
            \global\let\tbmpar@inuse=Y%   
          }%
          \endgraf
          \tbmparMiddleSep
          \edef\tbmpar@tmp{tbmpar@botbox\the\value{zabspage}}%
          \@ifundefined{\tbmpar@tmp}{%
          }{%
            \expandafter\let\expandafter\tbmpar@currbox
                \csname\tbmpar@tmp\endcsname
            \unvbox\tbmpar@currbox
            \tbmpar@FreeBox\tbmpar@currbox
            \global\let\tbmpar@inuse=Y%   
          }%
        }%  
        \ifx\tbmpar@inuse Y%
          \splittopskip=\topskip
          \setbox0=\vsplit\tbmpar@box to\z@
          \boxmaxdepth=\maxdepth
          \setbox\tbmpar@box=\vbox to\textheight{%
            \unvbox\tbmpar@box
          }%
          \box\tbmpar@box
        \fi
      \endgroup
    }%
  }%  
}     

\makeatother

% Testing

\usepackage[
  a5paper,   
  left=10mm, 
  right=10mm,
  marginparwidth=40mm,
  includemp,
]{geometry}
\usepackage{microtype}  
\usepackage[T1]{fontenc}
\usepackage{lmodern}

\clubpenalty=10000
\flushbottom
\settodepth\maxdepth{g}  
\setlength{\fboxsep}{1ex}
\usepackage{lipsum}
\usepackage{color}

\newcommand*{\shortlipsum}[1]{%
  \begingroup
    \long\def\y##1. ##2\@nil{##1.}%
    \edef\x{\csname lipsum@\romannumeral#1\endcsname}%
    \expandafter\y\x. \@nil
  \endgroup
}

\begin{document}
  \topmarginpar{\color{blue}\shortlipsum{1}}
  \lipsum[1]
  \botmarginpar{%
    Show effect of \texttt{\textbackslash maxdepth}:
    $\displaystyle\sum_{\textstyle i=\frac{a}{g}}^\infty i = x$}
  \lipsum[2]
  \topmarginpar{\shortlipsum{3}}%
  \botmarginpar{Second bottom marginal note}%
  \lipsum[3-4]
  \noindent a\botmarginpar{a} b\botmarginpar{b} c \botmarginpar{c} d\\
  e\\f\par
  \topmarginpar{\fbox{\shortlipsum{5}}}
  \lipsum[5]
  Text with footnote and marginal note\footnote{Marginal note X}.
  \topmarginpar{This is marginal note X}
  \lipsum[6]
  \botmarginpar{\shortlipsum{7}}
  \lipsum[7]  
\end{document}

結果

答案2

這是一個嘗試使用馬丁·沙勒的包裹tikz頁面節點。因為它使用remember picture, overlay的選項蒂克茲,您需要編譯兩次才能正確。它提供了兩個命令\marpartop,並且\marparbot都帶有兩個參數:內容和文字顏色,可以輕鬆擴展以更加可自訂。

程式碼

\documentclass{scrartcl}
\usepackage[left=15mm,top=40mm,bottom=40mm,right=50mm,a4paper]{geometry}
\usepackage{tikzpagenodes}
\usepackage{xifthen}

\usepackage{lipsum}

\setlength{\marginparwidth}{40mm}
\pagestyle{empty}

\def\myyshifttop{0}
\def\mypagetop{0}

\newcommand{\marpartop}[2]% content, color
{   \begin{tikzpicture}[remember picture, overlay]
        \ifthenelse{\thepage=\mypagetop}{}{\xdef\myyshifttop{0}}        
        \xdef\mypagetop{\thepage}
        \node[below right, yshift=\myyshifttop, text width=\marginparwidth-4pt, inner sep=2pt, #2] (tempnode) at (current page marginpar area.north west) {#1};
        \path (current page marginpar area.north west);
        \pgfgetlastxy{\tempxone}{\tempyone}
        \path (tempnode.south west);
        \pgfgetlastxy{\tempxtwo}{\tempytwo}
        \pgfmathsetmacro{\diffy}{(\tempytwo-\tempyone)}
        \xdef\myyshifttop{\diffy}
    \end{tikzpicture}
}

\def\myyshiftbot{0}
\def\mypagebot{0}

\newcommand{\marparbot}[2]% content, color
{   \begin{tikzpicture}[remember picture, overlay]
        \ifthenelse{\thepage=\mypagebot}{}{\xdef\myyshiftbot{0}}        
        \xdef\mypagebot{\thepage}
        \node[above right, yshift=\myyshiftbot, text width=\marginparwidth-4pt, inner sep=2pt, #2] (tempnode) at (current page marginpar area.south west) {#1};
        \path (current page marginpar area.south west);
        \pgfgetlastxy{\tempxone}{\tempyone}
        \path (tempnode.north west);
        \pgfgetlastxy{\tempxtwo}{\tempytwo}
        \pgfmathsetmacro{\diffy}{(\tempytwo-\tempyone)}
        \xdef\myyshiftbot{\diffy}
    \end{tikzpicture}
}

\begin{document}
\marpartop{On a journey to find the cure for a Tatarigami's curse, Ashitaka finds himself in the middle of a war between the forest gods and Tatara, a mining colony.}{red}
\marparbot{What begins as an open and shut case of murder soon becomes a mini-drama of each of the jurors' prejudices and preconceptions about the trial, the accused, and each other.}{orange!50!gray}
\lipsum[1-3]
\marparbot{The defense and the prosecution have rested and the jury is filing into the jury room to decide if a young Spanish-American is guilty or innocent of murdering his father.}{green!50!gray}
\marpartop{In this quest he also meets San, the Mononoke Hime.}{blue}
\lipsum[4-7]
\marpartop{On a journey to find the cure for a Tatarigami's curse, Ashitaka finds himself in the middle of a war between the forest gods and Tatara, a mining colony.}{red}
\marparbot{What begins as an open and shut case of murder soon becomes a mini-drama of each of the jurors' prejudices and preconceptions about the trial, the accused, and each other.}{orange!50!gray}
\lipsum[8]
\marpartop{In this quest he also meets San, the Mononoke Hime.}{blue}
\marparbot{The defense and the prosecution have rested and the jury is filing into the jury room to decide if a young Spanish-American is guilty or innocent of murdering his father.}{green!50!gray}
\lipsum[9-12]
\end{document}

結果

在此輸入影像描述

答案3

(註:這是一個社區答案,因為最初的想法來自 Tom Bombadil。)

這是 Tom Bombadil 的答案的變體,有一些改進:

  • 這兩個巨集已\topmarginpar\botmarginpar要求命名。

  • 他們的第一個論點(選修的預設為空)是 TikZ 節點的一些選項(允許填充、繪製邊框等)。他們的第二個論點是該段落的內容。

  • 有一些計算可以修正 tikzpagenodes偶數頁的錯誤(編輯:Martin Scharer 反應非常積極:修復了錯誤的版本即將發佈到 CTAN。)。

  • 該程式碼使用let操作(和calcTikZ 庫)。我認為它比 PGF 調用更具可讀性。

限制:

  • \botmarginpar應該以相反的順序堆疊段落!
  • 如果堆疊已滿,則不會繼續下一頁。它會溢出頁面的上方或下方。
  • 如果在頁面的最後一段中呼叫\topmarginpar(或\bormarginpar),則頁邊空白段落可能會出現在下一頁上,但順序不正確。

這是兩頁(奇數然後偶數):

第一頁(奇數) 第二頁(偶數)

代碼(帶有我的評論):

\documentclass[twoside]{report}
\usepackage{tikzpagenodes}
\usepackage{xifthen}
\usetikzlibrary{calc}

\def\myyshifttop{0}
\def\mypagetop{0}
\newcommand{\topmarginpar}[2][]{% tikz options of node, content
  \begin{tikzpicture}[remember picture, overlay]
    % reset position on new page
    \ifthenelse{\thepage=\mypagetop}{}{\xdef\myyshifttop{0}\xdef\mypagetop{\thepage}}
    % a big path with many actions
    \path let
    % patch for bug in tikzpagenodes with even pages
    \p1=(current page marginpar area.north west),
    \p2=(current page marginpar area.north east)
    in \pgfextra{
      \pgfmathsetmacro{\xw}{\x1<\x2?\x1:\x2}
      \pgfmathsetmacro{\yw}{\y1<\y2?\y1:\y2}
      \edef\coord{\xw pt,\yw pt}
    }
    % draw topmarginpar
    node[below right, yshift=\myyshifttop, text width=\marginparwidth-4pt, inner sep=2pt, #1]
    (tempnode) at (\coord) {#2}
    % next position
    let \p1=(\coord), \p2=(tempnode.south west) in \pgfextra{
      \pgfmathsetmacro{\diffy}{(\y2-\y1)}
      \xdef\myyshifttop{\diffy}
    };
  \end{tikzpicture}%
}

\def\myyshiftbot{0}
\def\mypagebot{0}
\newcommand{\botmarginpar}[2][]{% tikz options of node, content
  \begin{tikzpicture}[remember picture, overlay]
    % reset position on new page
    \ifthenelse{\thepage=\mypagebot}{}{\xdef\myyshiftbot{0}\xdef\mypagebot{\thepage}}
    % a big path with many actions
    \path let
    % patch for bug in tikzpagenodes with even pages
    \p1=(current page marginpar area.south west),
    \p2=(current page marginpar area.south east)
    in \pgfextra{
      \pgfmathsetmacro{\xw}{\x1<\x2?\x1:\x2}
      \pgfmathsetmacro{\yw}{\y1<\y2?\y1:\y2}
      \edef\coord{\xw pt,\yw pt}
    }
    % draw botmarginpar
    node[above right, yshift=\myyshiftbot, text width=\marginparwidth-4pt, inner sep=2pt, #1]
    (tempnode) at (\coord) {#2}
    % next position
    let \p1=(\coord), \p2=(tempnode.north west) in \pgfextra{
      \pgfmathsetmacro{\diffy}{(\y2-\y1)}
      \xdef\myyshiftbot{\diffy}
    };
  \end{tikzpicture}%
}

\usepackage{lipsum}

\begin{document}
\topmarginpar[red,fill=yellow!30]{On a journey to find the cure for a
  Tatarigami's curse, Ashitaka finds himself in the middle of a war
  between the forest gods and Tatara, a mining colony.}%
\botmarginpar{What begins as an open and shut case of murder soon
  becomes a mini-drama of each of the jurors' prejudices and
  preconceptions about the trial, the accused, and each other.}%
\lipsum[1-3]%
\botmarginpar[font=\itshape\footnotesize,text=green!50!black]{The
  defense and the prosecution have rested and the jury is filing into
  the jury room to decide if a young Spanish-American is guilty or
  innocent of murdering his father.}%
\topmarginpar[blue]{In this quest he also meets San, the Mononoke
  Hime.}%
\lipsum[4-7]%
\topmarginpar[red]{On a journey to find the cure for a Tatarigami's
  curse, Ashitaka finds himself in the middle of a war between the
  forest gods and Tatara, a mining colony.}%
\botmarginpar[orange!50!gray]{What begins as an open and shut case of
  murder soon becomes a mini-drama of each of the jurors' prejudices and
  preconceptions about the trial, the accused, and each other.}%
\lipsum[8]%
\topmarginpar[blue]{In this quest he also meets San, the Mononoke
  Hime.}%
\botmarginpar[green!50!gray]{The defense and the prosecution have rested
  and the jury is filing into the jury room to decide if a young
  Spanish-American is guilty or innocent of murdering his father.}%
\lipsum[9-12]
\end{document}

答案4

我對包做了一個簡單的破解marginfit並得到了一個簡單的解決方案。

\documentclass[11pt,a4paper]{article}

%% Needs marginfit package to be loaded before:
\RequirePackage{marginfit}

\makeatletter
%% Top marginpar:
\def\marginfit@writepost#1{%
    \write\@auxout{\string\@newl@bel{label@marginfit}{#1}{47040224}}%  %% Note it from aux file entry with @t
}
\def\marginpart{%
    \global\advance\c@marginfit@w\@ne%
    \expandafter\marginfit@writepost\expandafter{\the\c@marginfit@w @m}%
    \@ifnextchar[\marginfit@mpar@ii\marginfit@mpar@i%
}
%% Bottom marginpar:
\def\marginfit@writeposb#1{%
    \write\@auxout{\string\@newl@bel{label@marginfit}{#1}{0}}%  %% Minimum is 0
}
\def\marginparb{%
    \global\advance\c@marginfit@w\@ne%
    \expandafter\marginfit@writeposb\expandafter{\the\c@marginfit@w @m}%
    \@ifnextchar[\marginfit@mpar@ii\marginfit@mpar@i%
}
\makeatother


\begin{document}

\marginpar{OM O MO M M M M M M}

ABC

ABC

ABC

ABC

ABC

ABC

ABC

ABC

ABC


\marginpar{OM O MO M M M M M M\par\medskip\hrule}


ABC


\marginpart{To be Top OM O MO M M M M M M}


\newpage  %--------------------------------------------------------------------


ABC

ABC

ABC

ABC

ABC

ABC

ABC

ABC

ABC


\marginpart{Top OM O MO M M M M M M}

\marginparb{Bottom OM O MO M M M M M M}


ABC

ABC

ABC

ABC

\end{document}

\marginpart它為頂部邊距和\marginparb底部邊距提供了兩個新命令。其中的數字 47040224\pdflastypos代表最高保證金。該數字還可以更高,marginfit將在最終放置中設置其位置,以便它不會穿過頂部邊緣。根據您的頁面大小嘗試更高的值。最好的解決方法是先在文件的開頭建立單獨的 marginpar,使其位於最頂部,然後查看 aux 檔案中的條目。

它是這樣工作的:marginfit包用指定的標籤保存所有 marginpars 的 y 位置。我只是藉用了將當前 marginpar 的 ypos 寫入 aux 檔案的程式碼,並將 ypos 設為最大值(底部 marginpar 的最小值為 0)。

相關內容