%20Sie%20%5Cmarginpar%20an%20den%20Anfang%20oder%20das%20Ende%20der%20Seite..png)
Ich möchte etwas wie definieren
\topmarginpar{<text>}
, das im Wesentlichen ein erstellt\marginpar{<text>}
und dessen Oberseite mit der Oberseite der aktuellen Seite ausrichtet.Ich möchte
\topmarginpar
diese Objekte auch durch mehrere Aufrufe stapeln\marginpar
(anstatt sie überlappen zu lassen).Und schließlich möchte ich einen ähnlichen
\bottommargin
Befehl erstellen.
Gibt es ein bestehendes Paket, das diese Funktionalität bereitstellt, oder bin ich hier auf mich allein gestellt (ich beherrsche LaTeX, bin aber mit reinem TeX nicht vertraut)?
Danke für alle Vorschläge ...
Antwort1
Diese Lösung befasst sich mit der asynchronen Ausgaberoutine:
Die Seiten werden durch absolute Seitenzahlen identifiziert und die richtigen Seitenzahlen stehen im zweiten LaTeX-Durchlauf durch Labels zur Verfügung.
Jede Seite erhält zwei Sammelboxen, die die Randnotizen für den oberen und unteren Rand sammeln. Beim Versand ist die absolute Seitenzahl bekannt und die Sammelboxen für die Seite werden im Bereich "marginpar" der Seite ausgegeben.
Boxregister werden dynamisch zugeordnet und in einem Pool verwaltet. Nach dem Versand einer Seite werden die zugehörigen Collector-Boxregister freigegeben und wieder in den Pool zurückgelegt.
\topskip
und\maxdepth
werden für den „Randbereich“ respektiert.Zu viele Randnotizen auf einer Seite werden als Überfüllungswarnung gemeldet
\vbox
.LaTeX
\marginpar
wird nicht unterstützt, die Randnotizen unterschiedlicher Art kennen sich nicht und überdrucken sich munter gegenseitig.
Das Beispieldokument:
\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}
Antwort2
Hier ist ein Versuch mitMartin Scharrer's PaketAbonnieren. Da es die remember picture, overlay
Möglichkeiten vonTikZ, Sie müssen es zweimal kompilieren, damit es richtig funktioniert. Es stellt die beiden Befehle bereit \marpartop
, \marparbot
die beide zwei Argumente annehmen: den Inhalt und die Textfarbe. Dies könnte leicht erweitert werden, um es anpassbarer zu machen.
Code
\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}
Ergebnis
Antwort3
(Hinweis: Dies ist eine Community-Antwort, da die ursprüngliche Idee von Tom Bombadil stammt.)
Hier ist eine Variante von Tom Bombadils Antwort mit einigen Verbesserungen:
Die beiden Makros sind benannt
\topmarginpar
und\botmarginpar
entsprechen der Anforderung.Ihr erstes Argument (Optionalund standardmäßig leer) sind einige Optionen für den TikZ-Knoten (um Füllen, Zeichnen eines Rahmens usw. zu ermöglichen). Ihr zweites Argument ist der Inhalt des Absatzes.
Es gibt einige Berechnungen, um einen Fehler
tikzpagenodes
mit gerader Seite zu korrigieren (Bearbeiten: Martin Scharer reagiert sehr schnell: Eine Version mit behobenen Fehlern kommt zu CTAN.).Der Code verwendet
let
Operationen (undcalc
die TikZ-Bibliothek). Ich denke, er ist lesbarer als PGF-Aufrufe.
Grenzen:
\botmarginpar
Absätze sollten in umgekehrter Reihenfolge gestapelt werden!- Wenn ein Stapel voll ist, wird er nicht mit der nächsten Seite fortgesetzt. Er läuft auf der Seite nach oben oder unten über.
- Wenn
\topmarginpar
(oder\bormarginpar
) im letzten Absatz einer Seite aufgerufen wird, kann es sein, dass der Randabsatz auf der nächsten Seite und nicht in der richtigen Reihenfolge erscheint.
Hier sind zwei Seiten (erst ungerade und dann gerade):
Der Code (mit meinen Kommentaren):
\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}
Antwort4
Ich habe das Paket einfach gehackt marginfit
und eine einfache Lösung erhalten.
\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}
Es bietet zwei neue Befehle \marginpart
für den oberen und \marginparb
unteren Rand. Die Nummer 47040224 steht \pdflastypos
für den obersten Rand. Diese Nummer kann noch höher sein, marginfit
um die endgültige Position so festzulegen, dass sie die obere Kante nicht überschreitet. Versuchen Sie je nach Seitengröße höhere Werte. Die beste Methode, dies herauszufinden, besteht darin, zunächst einen einzelnen Rand am Anfang des Dokuments zu erstellen, sodass er ganz oben steht, und seinen Eintrag in der AUX-Datei zu prüfen.
So funktioniert es: marginfit
Das Paket speichert die Y-Position aller Randparameter mit einem zugewiesenen Label. Ich habe einfach den Code übernommen, der die Y-Position des aktuellen Randparameters in die AUX-Datei schreibt, und ihn so eingerichtet, dass die Y-Position auf das Maximum (und das Minimum 0 für den unteren Randparameter) gesetzt wird.