![Enviar (y apilar) \marginpar al principio o al final de la página](https://rvso.com/image/254706/Enviar%20(y%20apilar)%20%5Cmarginpar%20al%20principio%20o%20al%20final%20de%20la%20p%C3%A1gina.png)
Estoy buscando definir algo como
\topmarginpar{<text>}
, que esencialmente crearía\marginpar{<text>}
y alinearía su parte superior con la parte superior de la página actual.También me gustaría que se realicen varias
\topmarginpar
llamadas para apilar estos\marginpar
objetos (en lugar de superponerlos).Y finalmente me gustaría crear un
\bottommargin
comando similar.
¿Existe algún paquete que proporcione esta funcionalidad, o estoy solo aquí (soy fluido en LaTeX pero no valgo nada en TeX sin formato)?
Gracias por cualquier sugerencia...
Respuesta1
Esta solución se ocupa de la rutina de salida asincrónica:
Las páginas se identifican mediante números de página absolutos y los números de página correctos están disponibles en la segunda ejecución de LaTeX mediante etiquetas.
Cada página recibe dos cajas colectoras que recogen las notas marginales de la parte superior e inferior. En el momento del envío, se conoce el número absoluto de página y los cuadros recopiladores de la página se muestran en el área "marginpar" de la página.
Los registros de caja se asignan dinámicamente y se administran en un grupo. Después del envío de una página, los registros de su caja colectora se liberan y se devuelven al grupo.
\topskip
y\maxdepth
son respetados por el área de "margenpar".Demasiadas notas marginales en una página se consideran
\vbox
advertencias de exceso de contenido.LaTeX
\marginpar
no es compatible, las notas marginales de diferentes tipos no se conocen entre sí y se sobreimprimirán felizmente.
El documento de ejemplo:
\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}
Respuesta2
Aquí hay un intento usandoMartín Scharrerel paquetetikzpagenodes. Como utiliza las remember picture, overlay
opciones deTikZ, necesitarás compilar dos veces para hacerlo bien. Proporciona los dos comandos \marpartop
y \marparbot
ambos toman dos argumentos: el contenido y el color del texto, esto podría ampliarse fácilmente para que sea más personalizable.
Código
\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}
Resultado
Respuesta3
(Nota: es una respuesta de la comunidad porque la idea original es de Tom Bombadil).
Aquí hay una variante de la respuesta de Tom Bombadil con algunas mejoras:
Las dos macros tienen el nombre
\topmarginpar
y\botmarginpar
la solicitud.Su primer argumento (opcionaly vacío por defecto) son algunas opciones para el nodo TikZ (permitir rellenar, dibujar un borde, etc.). Su segundo argumento es el contenido del párrafo.
Hay algunos cálculos para corregir un error
tikzpagenodes
con páginas pares (editar: Martin Scharer es muy reactivo: llegará a CTAN una versión con errores corregidos.).El código utiliza
let
operaciones (ycalc
la biblioteca TikZ). Creo que es más legible que las llamadas PGF.
Límites:
\botmarginpar
¡Debería apilar los párrafos en orden inverso!- Si una pila está llena, no continúa a la página siguiente. Se desborda hacia arriba o hacia abajo en la página.
- Si se llama
\topmarginpar
(o ) en el último párrafo de una página, el párrafo del margen puede aparecer en la página siguiente y no en el orden correcto.\bormarginpar
Aquí hay dos páginas (pares e impares):
El código (con mis comentarios):
\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}
Respuesta4
Hice un truco simple en marginfit
el paquete y obtuve una solución simple.
\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}
Proporciona dos nuevos comandos \marginpart
para el margen superior y \marginparb
el margen inferior. El número 47040224 que contiene es \pdflastypos
para el margen superior. Este número puede ser aún mayor, marginfit
fijará su posición en la ubicación final para que no cruce el borde superior. Pruebe valores más altos dependiendo del tamaño de su página. El mejor método para averiguarlo es crear primero un margen único al principio del documento para que esté en la parte superior y buscar su entrada en el archivo auxiliar.
Así es como funciona: marginfit
el paquete guarda la posición de todos los márgenes con una etiqueta asignada. Acabo de tomar prestado el código que escribe los ypos del marginpar actual en un archivo auxiliar y lo configuré para configurar ypos al máximo (y mínimo a 0 para el marginpar inferior).